Exemple #1
0
static void Camera_new (LIScrArgs* args)
{
	LIExtCamera* self;
	LIExtCameraModule* module;
	LIScrData* data;
	LIRenRender* render;
	LIRenVideomode mode;

	/* Allocate self. */
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_CAMERA);
	self = liext_camera_new (module);
	if (self == NULL)
		return;
	liext_camera_set_driver (self, LIALG_CAMERA_THIRDPERSON);

	/* Initialize the viewport. */
	render = limai_program_find_component (module->program, "render");
	if (render)
	{
		liren_render_get_videomode (render, &mode);
		liext_camera_set_viewport (self, 0, 0, mode.width, mode.height);
	}

	/* Allocate userdata. */
	data = liscr_data_new (args->script, args->lua, self, LIEXT_SCRIPT_CAMERA, liext_camera_free);
	if (data == NULL)
	{
		liext_camera_free (self);
		return;
	}
	liscr_args_seti_stack (args);
}
static void Widgets_draw (LIScrArgs* args)
{
	LIExtModule* module;

	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_WIDGETS);
	liwdg_manager_render (module->widgets);
}
static void Sound_get_listener_rotation (LIScrArgs* args)
{
	LIExtModule* module;

	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_SOUND);
	liscr_args_seti_quaternion (args, &module->listener_rotation);
}
static void Voxel_fill_region (LIScrArgs* args)
{
	int i;
	int count;
	int type = 0;
	LIExtModule* module;
	LIMatVector pos;
	LIMatVector size;
	LIVoxVoxel tile;
	LIVoxVoxel* tiles;

	/* Handle arguments. */
	if (!liscr_args_gets_vector (args, "point", &pos) ||
	    !liscr_args_gets_vector (args, "size", &size))
		return;
	if (size.x < 1.0f || size.y < 1.0f || size.z < 1.0f)
		return;
	liscr_args_gets_int (args, "tile", &type);
	livox_voxel_init (&tile, type);

	/* Allocate tiles. */
	count = (int) size.x * (int) size.y * (int) size.z;
	tiles = lisys_calloc (count, sizeof (LIVoxVoxel));
	if (tiles == NULL)
		return;
	for (i = 0 ; i < count ; i++)
		tiles[i] = tile;

	/* Paste tiles to the map. */
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_VOXEL);
	livox_manager_paste_voxels (module->voxels,
		(int) pos.x, (int) pos.y, (int) pos.z,
		(int) size.x, (int) size.y, (int) size.z, tiles);
	lisys_free (tiles);
}
static void Ai_solve_path (LIScrArgs* args)
{
	int i;
	LIAiPath* path;
	LIExtModule* module;
	LIMatVector point;
	LIMatVector start;
	LIMatVector end;

	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_AI);
	if (!liscr_args_gets_vector (args, "start", &start))
		return;
	if (!liscr_args_gets_vector (args, "start", &start) ||
	    !liscr_args_gets_vector (args, "target", &end))
		return;

	/* Solve the path. */
	path = liai_manager_solve_path (module->ai, &start, &end);
	if (path == NULL)
		return;

	/* Store the path to a table. */
	liscr_args_set_output (args, LISCR_ARGS_OUTPUT_TABLE_FORCE);
	for (i = 0 ; i < liai_path_get_length (path) ; i++)
	{
		liai_path_get_point (path, i, &point);
		liscr_args_seti_vector (args, &point);
	}
	liai_path_free (path);
}
Exemple #6
0
static void Terrain_new (LIScrArgs* args)
{
	int chunk_size;
	float grid_size;
	LIExtTerrain* self;
	LIExtTerrainModule* module;
	LIScrData* data;

	/* Get the arguments. */
	if (!liscr_args_geti_int (args, 0, &chunk_size) || chunk_size < 1)
		return;
	if (!liscr_args_geti_float (args, 1, &grid_size) || grid_size <= 0.0f)
		return;
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_TERRAIN);

	/* Allocate the object. */
	self = liext_terrain_new (module, chunk_size, grid_size);
	if (self == NULL)
		return;

	/* Allocate the userdata. */
	data = liscr_data_new (args->script, args->lua, self, LIEXT_SCRIPT_TERRAIN, liext_terrain_free);
	if (data == NULL)
	{
		liext_terrain_free (self);
		return;
	}
	liscr_args_seti_stack (args);
}
Exemple #7
0
static void Heightmap_new (LIScrArgs* args)
{
	int i;
	int size;
	float spacing;
	float scaling;
	LIExtHeightmap* heightmap;
	LIExtHeightmapModule* module;
	LIImgImage* image;
	LIMatVector position;
	LIScrData* data;

	/* Get arguments. */
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_HEIGHTMAP);
	if (!liscr_args_geti_vector (args, 0, &position))
		position = limat_vector_init (0.0f, 0.0f, 0.0f);
	if (!liscr_args_geti_int (args, 1, &size))
		size = 33;
	else if (size < 0)
		size = 0;
	if (!liscr_args_geti_float (args, 2, &spacing))
		spacing = 1.0f;
	else if (spacing <= 0.0f)
		spacing = 1.0f;
	if (!liscr_args_geti_float (args, 3, &scaling))
		scaling = 1.0f;
	else if (scaling <= 0.0f)
		scaling = 1.0f;
	if (liscr_args_geti_data (args, 4, LIEXT_SCRIPT_IMAGE, &data))
		image = liscr_data_get_data (data);
	else
		image = NULL;

	/* Ensure that the size is valid. */
	for (i = 32 ; i < 65536 ; i *= 2)
	{
		if (size == i + 1)
			break;
	}
	if (size != i + 1)
	{
		lisys_error_set (EINVAL, "invalid heightmap size");
		lisys_error_report ();
		return;
	}

	/* Allocate the heightmap. */
	heightmap = liext_heightmap_new (module, image, &position, size, spacing, scaling);
	if (heightmap == NULL)
		return;

	/* Allocate the userdata. */
	data = liscr_data_new (args->script, args->lua, heightmap, LIEXT_SCRIPT_HEIGHTMAP, liext_heightmap_free);
	if (data == NULL)
	{
		liext_heightmap_free (heightmap);
		return;
	}
	liscr_args_seti_stack (args);
}
Exemple #8
0
static void Model_get_total_model_count (LIScrArgs* args)
{
	LIMaiProgram* program;

	program = liscr_script_get_userdata (args->script, LISCR_SCRIPT_PROGRAM);
	liscr_args_seti_int (args, program->models->models->size);
}
Exemple #9
0
static void Model_copy (LIScrArgs* args)
{
	int shape_keys = 1;
	LIMaiProgram* program;
	LIMdlModel* self;
	LIScrData* data;

	/* Get arguments. */
	program = liscr_script_get_userdata (args->script, LISCR_SCRIPT_PROGRAM);
	liscr_args_geti_bool (args, 0, &shape_keys);

	/* Allocate the model. */
	self = limdl_model_new_copy (args->self, shape_keys);
	if (self == NULL)
		return;

	/* Allocate the unique ID. */
	if (!limdl_manager_add_model (program->models, self))
	{
		limdl_model_free (self);
		return;
	}

	/* Allocate userdata. */
	data = liscr_data_new (args->script, args->lua, self, LISCR_SCRIPT_MODEL, limdl_manager_free_model);
	if (data == NULL)
	{
		limdl_model_free (self);
		return;
	}
	liscr_args_seti_stack (args);
}
static void Widgets_find_widget (LIScrArgs* args)
{
	int x;
	int y;
	LIExtModule* module;
	LIWdgWidget* widget;
	LIMatVector vector;
	LIScrData* data;

	if (!liscr_args_gets_vector (args, "point", &vector) &&
	    !liscr_args_geti_vector (args, 0, &vector))
	{
		SDL_GetMouseState (&x, &y);
		vector = limat_vector_init (x, y, 0.0f);
	}

	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_WIDGETS);
	widget = liwdg_manager_find_widget_by_point (module->widgets, (int) vector.x, (int) vector.y);
	if (widget == NULL)
		return;
	data = liwdg_widget_get_script (widget);
	if (data == NULL)
		return;
	liscr_args_seti_data (args, data);
}
static void Sound_get_listener_velocity (LIScrArgs* args)
{
	LIExtModule* module;

	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_SOUND);
	liscr_args_seti_vector (args, &module->listener_velocity);
}
Exemple #12
0
static void Model_changed (LIScrArgs* args)
{
	LIMaiProgram* program;

	/* Invoke callbacks. */
	program = liscr_script_get_userdata (args->script, LISCR_SCRIPT_PROGRAM);
	lical_callbacks_call (program->callbacks, "model-changed", lical_marshal_DATA_PTR, args->self);
}
static void Sound_set_listener_velocity (LIScrArgs* args)
{
	LIExtModule* module;
	LIMatVector value;

	if (liscr_args_geti_vector (args, 0, &value))
	{
		module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_SOUND);
		module->listener_velocity = value;
	}
}
static void Sound_set_listener_rotation (LIScrArgs* args)
{
	LIExtModule* module;
	LIMatQuaternion value;

	if (liscr_args_geti_quaternion (args, 0, &value))
	{
		module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_SOUND);
		module->listener_rotation = value;
	}
}
static void Sound_set_music_volume (LIScrArgs* args)
{
#ifndef LI_DISABLE_SOUND
	float value;
	LIExtModule* module;

	if (liscr_args_geti_float (args, 0, &value))
	{
		module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_SOUND);
		liext_sound_set_music_volume (module, value);
	}
#endif
}
Exemple #16
0
static void Model_get_total_memory_used (LIScrArgs* args)
{
	int total;
	LIMaiProgram* program;
	LIAlgU32dicIter iter;

	program = liscr_script_get_userdata (args->script, LISCR_SCRIPT_PROGRAM);

	total = 0;
	LIALG_U32DIC_FOREACH (iter, program->models->models)
		total += limdl_model_get_memory (iter.value);
	liscr_args_seti_int (args, total);
}
static void Sound_set_music (LIScrArgs* args)
{
#ifndef LI_DISABLE_SOUND
	const char* value;
	LIExtModule* module;

	if (liscr_args_geti_string (args, 0, &value))
	{
		module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_SOUND);
		liext_sound_set_music (module, value);
	}
#endif
}
static void Sound_get_music_offset (LIScrArgs* args)
{
#ifndef LI_DISABLE_SOUND
	LIExtModule* module;

	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_SOUND);
	if (module->music != NULL)
		liscr_args_seti_float (args, lisnd_source_get_offset (module->music));
	else
		liscr_args_seti_float (args, 0.0f);
#else
	liscr_args_seti_float (args, 0.0f);
#endif
}
static void Sound_set_music_offset (LIScrArgs* args)
{
#ifndef LI_DISABLE_SOUND
	float value;
	LIExtModule* module;

	if (liscr_args_geti_float (args, 0, &value))
	{
		module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_SOUND);
		if (module->music != NULL)
			lisnd_source_set_offset (module->music, value);
	}
#endif
}
Exemple #20
0
static void Terrain_build_chunk_model (LIScrArgs* args)
{
	int grid_x;
	int grid_z;
	LIExtTerrain* self;
	LIExtTerrainModule* module;
	LIMatVector offset;
	LIMdlModel* model;
	LIScrData* data;

	/* Get the arguments. */
	self = args->self;
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_TERRAIN);
	if (!liscr_args_geti_int (args, 0, &grid_x) || grid_x < 0)
		return;
	if (!liscr_args_geti_int (args, 1, &grid_z) || grid_z < 0)
		return;
	if (!liscr_args_geti_vector (args, 2, &offset))
		offset = limat_vector_init (grid_x * self->grid_size, 0.0f, grid_z * self->grid_size);

	/* Build the model. */
	model = liext_terrain_build_chunk_model (self, grid_x, grid_z, &offset);
	if (model == NULL)
		return;

	/* Copy the model. */
	model = limdl_model_new_copy (model, 0);
	if (model == NULL)
		return;

	/* Allocate the unique ID. */
	if (!limdl_manager_add_model (module->program->models, model))
	{
		limdl_model_free (model);
		return;
	}

	/* Allocate the userdata. */
	data = liscr_data_new (args->script, args->lua, model, LISCR_SCRIPT_MODEL, limdl_manager_free_model);
	if (data == NULL)
	{
		limdl_model_free (model);
		return;
	}
	liscr_args_seti_stack (args);
}
static void Widgets_get_focused_widget (LIScrArgs* args)
{
	int x;
	int y;
	LIExtModule* module;
	LIWdgWidget* widget;
	LIScrData* data;

	SDL_GetMouseState (&x, &y);
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_WIDGETS);
	widget = liwdg_manager_find_widget_by_point (module->widgets, x, y);
	if (widget == NULL)
		return;
	data = liwdg_widget_get_script (widget);
	if (data == NULL)
		return;
	liscr_args_seti_data (args, data);
}
static void Thread_new (LIScrArgs* args)
{
	const char* args_ = "";
	const char* file = "main.lua";
	const char* code = NULL;
	LIExtModule* module;

	/* Read arguments. */
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_THREAD);
	if (!liscr_args_geti_string (args, 0, &file))
	    liscr_args_gets_string (args, "file", &file);
	if (!liscr_args_geti_string (args, 1, &args_))
	    liscr_args_gets_string (args, "args", &args_);
	if (!liscr_args_geti_string (args, 2, &code))
	    liscr_args_gets_string (args, "code", &code);

	/* Create the thread to the stack. */
	if (liext_thread_inst_new (module->program, args->lua, file, code, args_) != NULL)
		liscr_args_seti_stack (args);
}
Exemple #23
0
static void Animation_load (LIScrArgs* args)
{
	char* file;
	const char* path;
	const char* name;
	LIMdlAnimation* self;
	LIExtAnimationModule* module;
	LIScrData* data;

	/* Get arguments. */
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_ANIMATION);
	if (!liscr_args_geti_string (args, 0, &name))
		return;

	/* Create the path. */
	file = lisys_string_concat (name, ".lani");
	if (file == NULL)
		return;
	path = lipth_paths_find_file (module->program->paths, file);
	lisys_free (file);
	if (path == NULL)
		return;

	/* Allocate the animation. */
	self = limdl_animation_new_from_file (path);
	if (self == NULL)
	{
		lisys_error_report ();
		return;
	}

	/* Allocate the userdata. */
	data = liscr_data_new (args->script, args->lua, self, LIEXT_SCRIPT_ANIMATION, limdl_animation_free);
	if (data == NULL)
	{
		limdl_animation_free (self);
		return;
	}
	liscr_args_seti_stack (args);
}
Exemple #24
0
static void Widget_new (LIScrArgs* args)
{
	LIExtModule* module;
	LIScrData* data;
	LIWdgWidget* self;

	/* Allocate userdata. */
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_WIDGET);
	self = liwdg_widget_new (module->widgets);
	if (self == NULL)
		return;

	/* Allocate userdata. */
	data = liscr_data_new (args->script, args->lua, self, LIEXT_SCRIPT_WIDGET, liwdg_widget_free);
	if (data == NULL)
	{
		liwdg_widget_free (self);
		return;
	}
	liwdg_widget_set_script (self, data);
	liscr_args_seti_stack (args);
}
static void Widgets_add_font_style (LIScrArgs* args)
{
	int size = 16;
	const char* file;
	const char* name;
	LIExtModule* module;

	/* Arguments. */
	if (!liscr_args_geti_string (args, 0, &name) &&
	    !liscr_args_gets_string (args, "name", &name))
		return;
	if (!liscr_args_geti_string (args, 1, &file) &&
	    !liscr_args_gets_string (args, "file", &file))
		return;
	if (!liscr_args_geti_int (args, 2, &size))
	    liscr_args_gets_int (args, "size", &size);

	/* Load the font. */
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_WIDGETS);
	if (!liwdg_styles_load_font (module->widgets->styles, name, file, size))
		lisys_error_report ();
}
Exemple #26
0
static void Model_load (LIScrArgs* args)
{
	int mesh = 1;
	char* file;
	const char* name;
	const char* path;
	LIMdlModel* tmpmdl;
	LIMaiProgram* program;

	program = liscr_script_get_userdata (args->script, LISCR_SCRIPT_PROGRAM);
	if (!liscr_args_geti_string (args, 0, &name) &&
	    !liscr_args_gets_string (args, "file", &name))
		return;
	if (!liscr_args_geti_bool (args, 1, &mesh))
		liscr_args_gets_bool (args, "mesh", &mesh);

	/* Find the absolute path. */
	file = lisys_string_concat (name, ".lmdl");
	if (file == NULL)
		return;
	path = lipth_paths_find_file (program->paths, file);
	if (path == NULL)
	{
		lisys_free (file);
		return;
	}
	lisys_free (file);

	/* Load the new model data. */
	tmpmdl = limdl_model_new_from_file (path, mesh);
	if (tmpmdl == NULL)
		return;

	/* Replace the old model data. */
	if (limdl_model_replace (args->self, tmpmdl))
		liscr_args_seti_bool (args, 1);
	limdl_model_free (tmpmdl);
}
static void Sound_effect (LIScrArgs* args)
{
#ifndef LI_DISABLE_SOUND
	int tmp;
	int flags = 0;
	float pitch;
	float volume;
	const char* effect;
	LIEngObject* object;
	LIExtModule* module;
	LIMatVector velocity;
	LIScrData* data;
	LISndSource* source;

	if (liscr_args_gets_string (args, "effect", &effect) &&
	    liscr_args_gets_data (args, "object", LISCR_SCRIPT_OBJECT, &data))
	{
		if (liscr_args_gets_bool (args, "positional", &tmp) && !tmp)
			flags |= LIEXT_SOUND_FLAG_NONPOSITIONAL;
		if (liscr_args_gets_bool (args, "repeating", &tmp) && tmp)
			flags |= LIEXT_SOUND_FLAG_REPEAT;
		object = liscr_data_get_data (data);
		module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_SOUND);
		source = liext_sound_set_effect (module, object->id, effect, flags);
		if (source != NULL)
		{
			if (liscr_args_gets_float (args, "pitch", &pitch))
				lisnd_source_set_pitch (source, pitch);
			if (liscr_args_gets_float (args, "volume", &volume))
				lisnd_source_set_volume (source, volume);
			if (liscr_args_gets_vector (args, "velocity", &velocity))
				lisnd_source_set_velocity (source, &velocity);
		}
	}
#endif
}
static void Voxel_find_blocks (LIScrArgs* args)
{
	int sx;
	int sy;
	int sz;
	int index;
	int line;
	int stamp;
	float radius;
	LIAlgRange sectors;
	LIAlgRange blocks;
	LIAlgRange range;
	LIAlgRangeIter iter0;
	LIAlgRangeIter iter1;
	LIExtModule* module;
	LIMatVector min;
	LIMatVector max;
	LIMatVector point;
	LIMatVector size;
	LIVoxBlock* block;
	LIVoxSector* sector;

	/* Initialize arguments. */
	if (!liscr_args_gets_vector (args, "point", &point))
		return;
	liscr_args_gets_float (args, "radius", &radius);
	liscr_args_set_output (args, LISCR_ARGS_OUTPUT_TABLE_FORCE);
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_VOXEL);
	line = module->voxels->blocks_per_line * module->voxels->sectors->count;

	/* Calculate sight volume. */
	size = limat_vector_init (radius, radius, radius);
	min = limat_vector_subtract (point, size);
	max = limat_vector_add (point, size);
	sectors = lialg_range_new_from_aabb (&min, &max, module->voxels->sectors->width);
	sectors = lialg_range_clamp (sectors, 0, module->voxels->sectors->count - 1);
	blocks = lialg_range_new_from_aabb (&min, &max, module->voxels->sectors->width / module->voxels->blocks_per_line);
	blocks = lialg_range_clamp (blocks, 0, module->voxels->blocks_per_line * module->voxels->sectors->count - 1);

	/* Loop through visible sectors. */
	LIALG_RANGE_FOREACH (iter0, sectors)
	{
		/* Get voxel sector. */
		sector = lialg_sectors_data_index (module->voxels->sectors, LIALG_SECTORS_CONTENT_VOXEL, iter0.index, 0);
		if (sector == NULL)
			continue;

		/* Calculate visible block range. */
		livox_sector_get_offset (sector, &sx, &sy, &sz);
		sx *= module->voxels->blocks_per_line;
		sy *= module->voxels->blocks_per_line;
		sz *= module->voxels->blocks_per_line;
		range.min = 0;
		range.max = module->voxels->blocks_per_line;
		range.minx = LIMAT_MAX (blocks.minx - sx, 0);
		range.miny = LIMAT_MAX (blocks.miny - sy, 0);
		range.minz = LIMAT_MAX (blocks.minz - sz, 0);
		range.maxx = LIMAT_MIN (blocks.maxx - sx, module->voxels->blocks_per_line - 1);
		range.maxy = LIMAT_MIN (blocks.maxy - sy, module->voxels->blocks_per_line - 1);
		range.maxz = LIMAT_MIN (blocks.maxz - sz, module->voxels->blocks_per_line - 1);

		/* Loop through visible blocks. */
		LIALG_RANGE_FOREACH (iter1, range)
		{
			block = livox_sector_get_block (sector, iter1.x, iter1.y, iter1.z);
			stamp = livox_block_get_stamp (block);
			index = (sx + iter1.x) + (sy + iter1.y) * line + (sz + iter1.z) * line * line;
			liscr_args_setf_float (args, index, stamp);
		}
static void Voxel_copy_region (LIScrArgs* args)
{
	int i;
	int length;
	int sector;
	int offset[3];
	LIArcPacket* packet;
	LIScrData* data;
	LIExtModule* module;
	LIMatVector point;
	LIMatVector size;
	LIVoxVoxel* result;

	/* Get region offset and size. */
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_VOXEL);
	if (liscr_args_gets_int (args, "sector", &sector))
	{
		lialg_sectors_index_to_offset (module->program->sectors, sector,
			offset + 0, offset + 1, offset + 2);
		point = limat_vector_init (offset[0], offset[1], offset[2]);
		point = limat_vector_multiply (point, module->voxels->tiles_per_line);
		size.x = size.y = size.z = module->voxels->tiles_per_line;
		length = module->voxels->tiles_per_sector;
	}
	else if (liscr_args_gets_vector (args, "point", &point) &&
	         liscr_args_gets_vector (args, "size", &size))
	{
		if (point.x < 0.0f || point.y < 0.0f || point.z < 0.0f ||
		    size.x < 1.0f || size.y < 1.0f || size.z < 1.0f)
			return;
		length = (int) size.x * (int) size.y * (int) size.z;
	}
	else
		return;

	/* Read voxel data. */
	result = lisys_calloc (length, sizeof (LIVoxVoxel));
	if (result == NULL)
		return;
	livox_manager_copy_voxels (module->voxels,
		(int) point.x, (int) point.y, (int) point.z,
		(int) size.x, (int) size.y, (int) size.z, result);

	/* Create a packet writer. */
	packet = liarc_packet_new_writable (0);
	if (packet == NULL)
	{
		lisys_free (result);
		return;
	}

	/* Write the dimensions. */
	if (!liarc_writer_append_uint32 (packet->writer, (int) size.x) ||
		!liarc_writer_append_uint32 (packet->writer, (int) size.y) ||
		!liarc_writer_append_uint32 (packet->writer, (int) size.z))
	{
		lisys_free (result);
		return;
	}

	/* Write voxel data. */
	for (i = 0 ; i < length ; i++)
	{
		if (!livox_voxel_write (result + i, packet->writer))
		{
			lisys_free (result);
			return;
		}
	}
	lisys_free (result);

	/* Return data. */
	data = liscr_data_new (args->script, args->lua, packet, LISCR_SCRIPT_PACKET, liarc_packet_free);
	if (data == NULL)
	{
		liarc_packet_free (packet);
		return;
	}
	liscr_args_seti_stack (args);
}
/**
    Script callback Los.heightmap_generate
      This function converts the image data to Voxels:
      <li>First image contains height information in color values</li>
      <li>Second image contains material information in color values</li>
      <li>Position is the lower inferior voxel of the mapped area</li>
      <li>Size is the volume of the mapped area. Base size must fit with image size</li>
      <li>Materials is an array of mat ID used to associate voxel types</li>
    
    \param LIScrArgs* args
*/
static void Heightmap_heightmap_generate (LIScrArgs* args)
{
	LIExtModule* module;
	LIVoxManager* voxels;
	LIVoxVoxel* tmp;
    const char* map_file;
    const char* tiles_file;
	LIMatVector posv;
	LIMatVector sizev;
    int materials[MAX_TEXTURES];
    void* map_data;
    void* tiles_data;
	int min[3];
	int max[3];
    int size[3];
    int x,y,z, y2, i, value;
    
    printf("Starting heightmap generation\n");
    
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_HEIGHTMAP);
	voxels = limai_program_find_component (module->program, "voxels");
	if (voxels == NULL)
		return;
        
	if (!liscr_args_geti_string (args, 0, &map_file) &&
	    liscr_args_gets_string (args, "map", &map_file))
        return;
	if (!liscr_args_geti_string (args, 1, &tiles_file))
	    liscr_args_gets_string (args, "tiles", &tiles_file);
	if (!liscr_args_geti_vector (args, 2, &posv))
	    liscr_args_gets_vector (args, "pos", &posv);
	if (!liscr_args_geti_vector (args, 3, &sizev))
		liscr_args_gets_vector (args, "size", &sizev);
	if (!liscr_args_geti_intv (args, 4, MAX_TEXTURES, materials))
		liscr_args_gets_intv (args, "materials", MAX_TEXTURES, materials);

    if (liext_heightmap_generate(module, map_file, &map_data) != 0)
    {
        return;
    }
    if (liext_heightmap_generate(module, tiles_file, &tiles_data) != 0)
    {
        liext_heightmap_cleanup(module, &map_data);
        return;
    }
    
	/* Calculate the size of the area. */
    size[0] = sizev.x;
    size[1] = sizev.y;
    size[2] = sizev.z;
	min[0] = posv.x;
	min[1] = posv.y;
	min[2] = posv.z;
	max[0] = (int)posv.x + size[0];
	max[1] = (int)posv.y + size[1];
	max[2] = (int)posv.z + size[2];
    
    printf("Coords: %d %d %d / %d %d %d / %d %d %d\n", min[0], min[1], min[2], max[0], max[1], max[2], size[0], size[1], size[2]);

	/* Batch copy terrain data. */
	/* Reading all tiles at once is faster than operating on
	   individual tiles since there are fewer sector lookups. */
	tmp = lisys_calloc (size[0] * size[1] * size[2], sizeof (LIVoxVoxel));
	if (tmp == NULL)
    {
        liext_heightmap_cleanup(module, &map_data);
        liext_heightmap_cleanup(module, &tiles_data);
		return;
    }
	livox_manager_copy_voxels (voxels, min[0], min[1], min[2],
		size[0], size[1], size[2], tmp);

	/* Apply heightmap to the copied tiles. */
    i = 0;
	for (z = min[2] ; z < max[2] ; z++)
	for (y = min[1] ; y < max[1] ; y++)
	for (x = min[0] ; x < max[0] ; x++)
	{
        //TODO: better resolution
		y2 = 255 - liext_heightmap_find(module, x, z, map_data);
        printf("gen y: %d\n", y2);
        if (y2 != -1 && y <= y2)
        {
            value = liext_heightmap_find(module, x, z, tiles_data);
            if (value < 0 || value >= MAX_TEXTURES)
            {
                value = 0;
            }
            livox_voxel_init (tmp + i, 15 /* materials[value] */);
            printf("voxel: %d %d\n", i, value);
        }
        i++;
	}

	/* Batch write the copied tiles. */
	livox_manager_paste_voxels (voxels, min[0], min[1], min[2],
		size[0], size[1], size[2], tmp);
	lisys_free (tmp);
    
    printf("Area has been successfully loaded from heightmap\n");
    
    liext_heightmap_cleanup(module, &map_data);
    liext_heightmap_cleanup(module, &tiles_data);
}