/*------------------------------------------------------------------------*
  Filename....: random_trans_tool.c


		 COPYRIGHT (C) 2001.  All Rights Reserved.
		 auto*des*sys, Inc., Columbus, Ohio, USA.
 *------------------------------------------------------------------------*/

#include "random_trans.h"
#include "fz_tool_api.h"
#include "fz_cmnd_model_ids.h"

/* Global Variables */
double	tx_min=0, tx_max=0, ty_min=0, ty_max=0, tz_min=0, tz_max=0;
double	rx_min=0, rx_max=0, ry_min=0, ry_max=0, rz_min=0, rz_max=0;
double	sx_min=1, sx_max=1, sy_min=1, sy_max=1, sz_min=1, sz_max=1;
double	sU_min=1, sU_max=1;

fzrt_boolean	centroid = TRUE;

/************************************************************************
	info callback function for the random_trans tool command
*************************************************************************/
static fzrt_error_td random_trans_tool_info(fz_tool_kind_enum *kind, fz_proj_level_enum *level)
{
	fzrt_error_td			rv = FZRT_NOERR;

	*kind = FZ_TOOL_KIND_OPERATOR;
	*level = FZ_PROJ_LEVEL_MODEL;
	
	return (rv);
}

/************************************************************************
	init callback function for the random_trans tool command
*************************************************************************/
static fzrt_error_td random_trans_tool_init (
	void
	)
{
	plugin_stuff.syst_funcs.fz_syst_cmnd_set_status_of_objt(RANDOM_TRANS_TOOL_ID,TRUE,FALSE);
	return (FZRT_NOERR);
}


/************************************************************************
	name callback function for the random_trans tool command
*************************************************************************/
static fzrt_error_td random_trans_tool_name(char *name, fzrt_int max_len)
{
	char	str[256];
	
	plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, RANDOM_TRANS_STR_ID, RANDOM_TRANS_STR_TOOL_NAME, str);
	strncpy(name, str, max_len);
	
	return (FZRT_NOERR);
}

/************************************************************************
	uuid callback function for the random_trans tool command
*************************************************************************/
static fzrt_error_td random_trans_tool_uuid(fzrt_UUID_td uuid)
{

	plugin_stuff.fzrt_base_funcs.fzrt_UUID_copy( RANDOM_TRANS_TOOL_ID, uuid );
	
	return (FZRT_NOERR);
}

/************************************************************************
	icon file callback function for the random_trans tool command
*************************************************************************/
static fzrt_error_td random_trans_tool_icon_file(fzrt_floc_ptr floc)
{
fzrt_error_td	err=FZRT_NOERR;			/** DEK 09/19/06 ***/

	err = plugin_stuff.fzrt_file_funcs.fzrt_file_floc_copy(plugin_stuff.floc,floc);
	err = plugin_stuff.fzrt_file_funcs.fzrt_file_floc_set_name(floc,"random_trans.bmp");
	return(err);
}

/************************************************************************
	prefs io callback function for the random_trans tool command
**************************************************************************/
static fzrt_error_td random_trans_tool_pref_io(fz_iost_ptr iost, fz_iost_dir_td_enum dir, fzpl_vers_td * const version, fzrt_unsigned_int size)
{
	fzrt_error_td		err = FZRT_NOERR;

	if ( dir == FZ_IOST_WRITE ) *version = 0;
	

	return(err);
}

/************************************************************************
	units callback function for the random_trans tool command
**************************************************************************/
static fzrt_error_td random_trans_tool_syst_units(fz_unit_type_enum pref_units, fz_unit_scale_enum pref_scale)
{

	
	//plugin_stuff.fuim_funcs.fz_fuim_unit_convert(12.0, 25.0, FZ_UNIT_SCAL_MEDIUM, pref_units, pref_scale, &data->radius);
		
	

	return(FZRT_NOERR);
}
/************************************************************************
	preferences defaults callback function for the random_trans tool command
**************************************************************************/
static fzrt_error_td random_trans_tool_pref_default(fz_unit_type_enum pref_units, fz_unit_scale_enum pref_scale)
{

	//random_trans_tool_syst_units(pref_units, pref_scale);

	return(FZRT_NOERR);
}

/************************************************************************
	icon adjacent callback function for the random_trans tool command
*************************************************************************/
static fzrt_error_td random_trans_tool_tool_bar_adjacent(const fzrt_UUID_td tool_bar_id, fzrt_UUID_td adjacent_id, fz_fuim_icon_adjacent_enum *where)
{		
	plugin_stuff.fzrt_base_funcs.fzrt_UUID_copy(FZ_CMND_MODEL_DERV_PARL_PL, adjacent_id);
	*where = FZ_FUIM_ICON_ADJACENT_RIGHT;
	
	return(FZRT_NOERR);
}


/************************************************************************
	click callback function for the random_trans tool command
*************************************************************************/
static fzrt_error_td random_trans_tool_click(
		fzrt_int 						windex, 
		fzrt_point 					*where, 
		fz_xyz_td 					*where_3d, 
		fz_map_plane_td 			*map_plane,
		fz_fuim_click_enum 			clicks, 
		fzrt_int 						click_count,  
		fzrt_boolean 				*click_handled,
		fz_fuim_click_wait_enum 	*click_next, 
		fzrt_boolean 				*done)		
{
	fzrt_error_td		err=FZRT_NOERR;
	fz_xyz_td		rMOV, rROT, rSCL, centroid_loc;
	double			rUSCL;
	fzrt_int		num_objs,i ;
	fz_objt_ptr		object;
	fz_mat4x4_td	mat;               // Matrix used during calculations
	fz_mat4x4_td	final_mat;         // Final matrix to contain all transformations
	fz_mat4x4_td    scl_mat;           // Scale only matrix
	fz_mat4x4_td    rot_mat;           // Rotation only matrix
	fz_mat4x4_td    trl_mat;           // Translation only matrix
	
	
	if (click_count >= 1)
	{
		//  Count the number of selected objects
		plugin_stuff.model_funcs.fz_model_pick_get_count(windex,&num_objs);
		plugin_stuff.model_funcs.fz_model_pick_sort(windex,FZ_MODEL_PICK_SORT_ORDER);
		
		for(i=0; i<num_objs; i++)
		{
			/*  GET THE OBJECT TO BE TRANSFORMED  */
			plugin_stuff.model_funcs.fz_model_pick_get_data(windex, i, NULL, NULL, &object, NULL);
			
			if(centroid)
				//  Get the object centroid
				plugin_stuff.model_funcs.fz_objt_alys_get_objt_centroid(windex, object, &centroid_loc);
			else
				//  Get the object origin
				plugin_stuff.model_funcs.fz_objt_alys_get_objt_origin(windex, object, &centroid_loc);
			
			/*  Generate the random translation numbers  */
			rMOV.x = plugin_stuff.math_funcs.fz_math_random_range(tx_min, tx_max);
			rMOV.y = plugin_stuff.math_funcs.fz_math_random_range(ty_min, ty_max);
			rMOV.z = plugin_stuff.math_funcs.fz_math_random_range(tz_min, tz_max);
			
			rROT.x = plugin_stuff.math_funcs.fz_math_random_range(rx_min, rx_max);
			rROT.y = plugin_stuff.math_funcs.fz_math_random_range(ry_min, ry_max);
			rROT.z = plugin_stuff.math_funcs.fz_math_random_range(rz_min, rz_max);
			
			rUSCL = plugin_stuff.math_funcs.fz_math_random_range(sU_min, sU_max);
			
			rSCL.x = rUSCL * plugin_stuff.math_funcs.fz_math_random_range(sx_min, sx_max);
			rSCL.y = rUSCL * plugin_stuff.math_funcs.fz_math_random_range(sy_min, sy_max);
			rSCL.z = rUSCL * plugin_stuff.math_funcs.fz_math_random_range(sz_min, sz_max);
			
			/*  Transform the objects  */
			//  Set the scale numbers into the scale matrix
			plugin_stuff.math_funcs.fz_math_4x4_set_scl_cntr_mat(&scl_mat, &rSCL, &centroid_loc);
			
			//  Set the rotation numbers into the rotation matrix
			plugin_stuff.math_funcs.fz_math_4x4_set_rot_cntr_mat(&rot_mat, rROT.z, &centroid_loc, FZ_AXIS_Z);
			
			//  Multiply the rotate and scale matrices into the final matrix
			plugin_stuff.math_funcs.fz_math_4x4_multiply_mat_mat(&rot_mat,&scl_mat,&mat);
			
			plugin_stuff.math_funcs.fz_math_4x4_set_rot_cntr_mat(&rot_mat, rROT.y, &centroid_loc, FZ_AXIS_Y);
			plugin_stuff.math_funcs.fz_math_4x4_multiply_mat_mat(&mat,&rot_mat,&mat);
			
			plugin_stuff.math_funcs.fz_math_4x4_set_rot_cntr_mat(&rot_mat, rROT.x, &centroid_loc, FZ_AXIS_X);
			plugin_stuff.math_funcs.fz_math_4x4_multiply_mat_mat(&mat,&rot_mat,&mat);
			
			//  Set the movement numbers into the translation matrix
			plugin_stuff.math_funcs.fz_math_4x4_set_trl_mat(&trl_mat, &rMOV);
			
			//  Multiply the translation matrix into the final matrix
			plugin_stuff.math_funcs.fz_math_4x4_multiply_mat_mat(&trl_mat, &mat, &final_mat);
			
			//  Transform the object using the master matrix
			plugin_stuff.model_funcs.fz_objt_edit_transform_objt(windex, object, &final_mat);
		}
		done = TRUE;
	}

	return (err);
}


/************************************************************************
	tool options name callback function for the random_trans tool command
*************************************************************************/
static fzrt_error_td random_trans_tool_opts_name(char *name, fzrt_int max_len)
{
	char	str[256];
	
	plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, RANDOM_TRANS_STR_ID, RANDOM_TRANS_STR_OPTS_TITLE, str);
	strncpy(name, str, max_len);
	
	return (FZRT_NOERR);
}

/************************************************************************
	tool options uuid callback function for the random_trans tool command
*************************************************************************/
static fzrt_error_td random_trans_tool_opts_uuid(fzrt_UUID_td uuid)
{

	plugin_stuff.fzrt_base_funcs.fzrt_UUID_copy(RANDOM_TRANS_TOOL_OPTS_ID, uuid);
	
	return (FZRT_NOERR);
}
/************************************************************************
	button callback function. Handles Reset button for Move
 *************************************************************************/
static short	reset_move(  fz_fuim_tmpl_ptr		fuim_tmpl,
					 fzrt_int					action,
					 short					item_id,
					 void					*func_data,
					 fz_fuim_type_td			*rv_data
					 )
{
	short			rv = 0;
	
	switch(action)
	{
		case FZ_FUIM_ACTN_HIT:
			tx_min=tx_max=ty_min=ty_max=tz_min=tz_max=0;
			rv = 1;
			return(TRUE);
	}
	return(rv);
}

/************************************************************************
	button callback function. Handles Reset button for Move
 *************************************************************************/
static short	reset_rotate(  fz_fuim_tmpl_ptr		fuim_tmpl,
					   fzrt_int					action,
					   short					item_id,
					   void					*func_data,
					   fz_fuim_type_td			*rv_data
					   )
{
	short			rv = 0;
	
	switch(action)
	{
		case FZ_FUIM_ACTN_HIT:
			rx_min=rx_max=ry_min=ry_max=rz_min=rz_max=0;
			rv = 1;
			return(TRUE);
	}
	return(rv);

	return(TRUE);
}

/************************************************************************
	button callback function. Handles Reset button for Move
 *************************************************************************/
static short	reset_scale(  fz_fuim_tmpl_ptr		fuim_tmpl,
					  fzrt_int					action,
					  short					item_id,
					  void					*func_data,
					  fz_fuim_type_td			*rv_data
					  )
{	short			rv = 0;
	
	switch(action)
	{
		case FZ_FUIM_ACTN_HIT:
			sx_min=sx_max=sy_min=sy_max=sz_min=sz_max=1.0;
			rv = 1;
			return(TRUE);
	}
	return(rv);
}

/************************************************************************
	tool options dialog template callback function for the random_trans tool command
*************************************************************************/
static fzrt_error_td random_trans_tool_opts_fuim(fz_fuim_tmpl_ptr fuim_tmpl, fzrt_ptr fuim_data)
{
	fzrt_error_td		err=FZRT_NOERR;
	fz_string_td str;
	
	long				g0, g1, g2, g3, g4;
	long				topGroup, t;

	
	plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, RANDOM_TRANS_STR_ID, RANDOM_TRANS_STR_OPTS_TITLE, str);
	if((err = plugin_stuff.fuim_funcs.fz_fuim_tmpl_init(fuim_tmpl, str, 0, RANDOM_TRANS_TOOL_OPTS_ID, 0)) == FZRT_NOERR)
	{
		topGroup = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, FZ_FUIM_ROOT, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		
		/*  TRANSLATE  */
		g3 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, topGroup, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		g1 = plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_BRDR, "Move", NULL, NULL);
		
		g0 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		
		/*  Min X  */
		g1 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g0, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		g2 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Min", NULL, NULL);
		
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &tx_min, 0, 0, FZ_FUIM_FORMAT_FLOAT_DISTANCE, FZ_FUIM_RANGE_NONE);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &ty_min, 0, 0, FZ_FUIM_FORMAT_FLOAT_DISTANCE, FZ_FUIM_RANGE_NONE);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &tz_min, 0, 0, FZ_FUIM_FORMAT_FLOAT_DISTANCE, FZ_FUIM_RANGE_NONE);
		
		/*  Max X  */
		g1 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g0, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		g2 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Max", NULL, NULL);
		
		g3 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &tx_max, 0, 0, FZ_FUIM_FORMAT_FLOAT_DISTANCE, FZ_FUIM_RANGE_NONE);
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "X", NULL, NULL);
		g3 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &ty_max, 0, 0, FZ_FUIM_FORMAT_FLOAT_DISTANCE, FZ_FUIM_RANGE_NONE);
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, " Y", NULL, NULL);
		g3 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &tz_max, 0, 0, FZ_FUIM_FORMAT_FLOAT_DISTANCE, FZ_FUIM_RANGE_NONE);
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, " Z", NULL, NULL);
		
		plugin_stuff.fuim_funcs.fz_fuim_new_button(fuim_tmpl,g2,FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Reset", reset_move, NULL);
		
		
		/*  ROTATE  */
		g3 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, topGroup, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		g1 = plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_BRDR, "Rotate", NULL, NULL);
		
		g0 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		
		/*  Min X  */
		g1 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g0, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		g2 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Min", NULL, NULL);
		
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &rx_min, 0, 0, FZ_FUIM_FORMAT_FLOAT_ANGLE, FZ_FUIM_RANGE_NONE);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &ry_min, 0, 0, FZ_FUIM_FORMAT_FLOAT_ANGLE, FZ_FUIM_RANGE_NONE);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &rz_min, 0, 0, FZ_FUIM_FORMAT_FLOAT_ANGLE, FZ_FUIM_RANGE_NONE);
		
		/*  Max X  */
		g1 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g0, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		g2 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Max", NULL, NULL);
		
		g3 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &rx_max, 0, 0, FZ_FUIM_FORMAT_FLOAT_ANGLE, FZ_FUIM_RANGE_NONE);
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "X", NULL, NULL);
		g3 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &ry_max, 0, 0, FZ_FUIM_FORMAT_FLOAT_ANGLE, FZ_FUIM_RANGE_NONE);
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, " Y", NULL, NULL);
		g3 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &rz_max, 0, 0, FZ_FUIM_FORMAT_FLOAT_ANGLE, FZ_FUIM_RANGE_NONE);
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, " Z", NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_new_button(fuim_tmpl,g2,FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Reset", reset_rotate, NULL);
		
		
		/*  SCALE  */
		g3 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, topGroup, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		g4 = plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_BRDR, "Scale", NULL, NULL);
		
		g0 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g4, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		
		/*  Min X  */
		g1 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g0, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		g2 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Min", NULL, NULL);
		
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &sx_min, 0, 0, FZ_FUIM_FORMAT_FLOAT_DEFAULT, FZ_FUIM_RANGE_NONE);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &sy_min, 0, 0, FZ_FUIM_FORMAT_FLOAT_DEFAULT, FZ_FUIM_RANGE_NONE);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &sz_min, 0, 0, FZ_FUIM_FORMAT_FLOAT_DEFAULT, FZ_FUIM_RANGE_NONE);
		
		/*  Max X  */
		g1 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g0, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		g2 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Max", NULL, NULL);
		
		g3 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &sx_max, 0, 0, FZ_FUIM_FORMAT_FLOAT_DEFAULT, FZ_FUIM_RANGE_NONE);
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "X", NULL, NULL);
		g3 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &sy_max, 0, 0, FZ_FUIM_FORMAT_FLOAT_DEFAULT, FZ_FUIM_RANGE_NONE);
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, " Y", NULL, NULL);
		g3 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &sz_max, 0, 0, FZ_FUIM_FORMAT_FLOAT_DEFAULT, FZ_FUIM_RANGE_NONE);
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, " Z", NULL, NULL);
		
		plugin_stuff.fuim_funcs.fz_fuim_new_button(fuim_tmpl,g2,FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Reset", reset_scale, NULL);
		
		/*  Uniform Scale  */
		g0 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g4, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		
		/*  Min X  */
		g1 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g0, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		g2 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Uniform Min", NULL, NULL);
		
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &sU_min, 0, 0, FZ_FUIM_FORMAT_FLOAT_DEFAULT, FZ_FUIM_RANGE_NONE);
		
		/*  Max X  */
		g1 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g0, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		g2 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
		
		plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Uniform Max", NULL, NULL);
		
		g3 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		t = plugin_stuff.fuim_funcs.fz_fuim_new_text_edit(fuim_tmpl, g3, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, t, &sU_max, 0, 0, FZ_FUIM_FORMAT_FLOAT_DEFAULT, FZ_FUIM_RANGE_NONE);
		
		
		/*  Rotation Options  */
		
		g1 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, FZ_FUIM_ROOT, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		
		g2 = plugin_stuff.fuim_funcs.fz_fuim_new_text_static(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Rotate/Scale about its:", NULL, NULL);
		
		g1 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, FZ_FUIM_ROOT, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, NULL);
		
		g2 = plugin_stuff.fuim_funcs.fz_fuim_new_radio(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Centroid", NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_unary_bool(fuim_tmpl, g2, &centroid, TRUE);
		g2 = plugin_stuff.fuim_funcs.fz_fuim_new_radio(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, "Origin", NULL, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_item_unary_bool(fuim_tmpl, g2, &centroid, FALSE);
		
		
	}
	
	
	
	
	return (err);
}

/*************************************************************************
 tool info2 callback
 *************************************************************************/
static fzrt_boolean random_trans_tool_info2(
	 fzrt_int				windex,
	 fz_tool_info_enum	which,
	 fz_type_td			*info_data,
	 fz_type_td			*data
	 )
{
	fzrt_boolean		rv = TRUE;
	fzrt_int				value;
	
	switch(which)
	{ 
		case FZ_TOOL_INFO_PICK_STATE :
			value = 1;		/* PICKING ONE SET */
			plugin_stuff.type_funcs.fz_type_set_int(&value, data);
			break;
			
		default:
			rv = FALSE;
		break;
	}
	
	return(rv);
}

/************************************************************************
 pick set callback
 *************************************************************************/
static fzrt_error_td random_trans_tool_pick_set(fzrt_int windex, fzrt_int set_id, fzrt_int *set_count_min, fzrt_int *set_count_max, fzrt_int *set_topo_mask, fzrt_int *set_type_count, fzrt_UUID_td *set_type_list, fzrt_int *set_flags)
{
	fzrt_error_td		err = FZRT_NOERR;
	
	*set_type_count = 0;
	
	switch(set_id)
	{
		case 0 : 
			*set_count_min = 1;														/* AT LEAST ONE */
			*set_topo_mask = 0;
			FZ_SETBIT(*set_topo_mask, FZ_OBJT_PICK_LEVEL_OBJT);						/* OBJECTS ONLY */
			
			plugin_stuff.fzrt_base_funcs.fzrt_UUID_copy(FZ_OBJT_DATA_UUID, set_type_list[(*set_type_count)++]);	/* OBJECT CLASS */
		break;
			
	}
	return(err);
}

/*************************************************************************
 Pick valid callback
 *************************************************************************/
static fzrt_error_td random_trans_tool_pick_valid(
   fzrt_int				windex, 
   fzrt_int				set_id, 
   fzrt_UUID_td		type, 
   fz_tag_td		*item_tag,
   fzrt_UUID_td		part_class, 
   fzrt_int				part_id, 
   fzrt_UUID_td		sub_part_class, 
   fzrt_int				sub_part_id, 
   fzrt_boolean		*valid,
   fz_string_td 	nvalid_reason
   )
{
	fz_objt_ptr					obj;
	
	*valid = FALSE;
	
	/* SOURCE : ALLOW OBJECT TOPOLOGY */
	if( plugin_stuff.fzrt_base_funcs.fzrt_UUID_compare(type,FZ_OBJT_DATA_UUID) == 0 )
	{
		if( plugin_stuff.model_funcs.fz_objt_tag_to_ptr(windex, item_tag, &obj) == FZRT_NOERR)
		{
			*valid = TRUE;
#if 0
			if ( random_trans_otyp_check_radius(windex,obj,_random_trans_tool_opts->radius,NULL) == TRUE )
			{
				*valid = TRUE;
			}
			else
			{	/* "One or more segments are shorter than the random_trans radius" */
				plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, RANDOM_TRANS_STR_ID, RANDOM_TRANS_STR_NVALID_PICK, nvalid_reason);
			}
#endif
		}
	}
	
	return(FZRT_NOERR);
}

/************************************************************************
 JSP 10/08/08 : New function
 JSP 11/06/08  : adjusting function
 *************************************************************************/
static fzrt_boolean random_trans_tool_action(
	fzrt_int				windex,
	fz_tool_action_enum	which,
	fzrt_int				set_id, 
	fzrt_int				click_count, 
	char				*actn_string, 
	fzrt_int				actn_string_len
	)
{
	fzrt_boolean		rv = FALSE;
	
	switch(which)
	{
		case FZ_TOOL_ACTION_DESCRIPTION :
			plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, RANDOM_TRANS_STR_ID, RANDOM_TRANS_STR_DESC, actn_string);
			rv = TRUE;
		break;
			
		case FZ_TOOL_ACTION_PICK :
			plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, RANDOM_TRANS_STR_ID, RANDOM_TRANS_STR_PICK, actn_string);
			rv = TRUE;
		break;
			
		case FZ_TOOL_ACTION_CLICK :
			plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, RANDOM_TRANS_STR_ID, RANDOM_TRANS_STR_CLICK, actn_string);
			rv = TRUE;
		break;
		default:
		break;
	}
	return(rv);
}

/************************************************************************
	Fill the tool command function set with the star tool command callback
	functions.
*************************************************************************/
fzrt_error_td random_trans_tool_get_callback_fset ( const fzpl_fset_def_ptr fset_def, fzpl_fset_td * const fset )
{
	fzrt_error_td							err = FZRT_NOERR;
	fz_tool_cbak_fset 				*cmds_func;

	err = plugin_stuff.fsf->fzpl_fset_def_check ( fset_def, FZ_TOOL_CBAK_FSET_VERSION, FZPL_TYPE_STRING(fz_tool_cbak_fset), sizeof ( cmds_func ), FZPL_VERSION_OP_NEWER );
	if ( err == FZRT_NOERR )
	{
		cmds_func = (fz_tool_cbak_fset *)fset;
		
		cmds_func->fz_tool_cbak_init					= random_trans_tool_init;
		cmds_func->fz_tool_cbak_info					= random_trans_tool_info;
		cmds_func->fz_tool_cbak_name					= random_trans_tool_name;
		cmds_func->fz_tool_cbak_uuid					= random_trans_tool_uuid;
		cmds_func->fz_tool_cbak_icon_file				= random_trans_tool_icon_file;
		cmds_func->fz_tool_cbak_icon_menu_adjacent		= random_trans_tool_tool_bar_adjacent;
		
		cmds_func->fz_tool_cbak_pref_io					= random_trans_tool_pref_io;

		cmds_func->fz_tool_cbak_opts_name				= random_trans_tool_opts_name;
		cmds_func->fz_tool_cbak_opts_uuid				= random_trans_tool_opts_uuid;
		cmds_func->fz_tool_cbak_opts_iface_tmpl			= random_trans_tool_opts_fuim;
		cmds_func->fz_tool_cbak_click					= random_trans_tool_click;
		
		cmds_func->fz_tool_cbak_info2					= random_trans_tool_info2;
		cmds_func->fz_tool_cbak_pick_set				= random_trans_tool_pick_set;
		cmds_func->fz_tool_cbak_pick_valid				= random_trans_tool_pick_valid;
		cmds_func->fz_tool_cbak_action					= random_trans_tool_action;
		
	}

	return err;
}

/************************************************************************
	Fill the notification function set with the star tool notification callback
	functions.
*************************************************************************/
fzrt_error_td random_trans_notf_get_callback_fset ( const fzpl_fset_def_ptr fset_def, fzpl_fset_td * const fset )
{
	fzrt_error_td						err = FZRT_NOERR;
	fz_notf_cbak_fset 				*notf_func;

	plugin_stuff.fsf->fzpl_fset_def_check ( fset_def, FZ_NOTF_CBAK_FSET_VERSION, FZPL_TYPE_STRING(fz_notf_cbak_fset), sizeof ( notf_func ), FZPL_VERSION_OP_NEWER );
	if ( err == FZRT_NOERR )
	{
		notf_func = (fz_notf_cbak_fset *)fset;
		
		notf_func->fz_notf_cbak_syst_units		= random_trans_tool_syst_units;
		notf_func->fz_notf_cbak_pref_default	= random_trans_tool_pref_default;

	}

	return err;
}

