/*------------------------------------------------------------------------*
  Filename....: star_otyp.c


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

#include "star.h"


/************************************************************************
	Get the mapping plane of a star object
*************************************************************************/
static void star_otyp_get_mplane(star_otyp_parms_td *star, fz_map_plane_td *plane)
{
	fz_xyz_td	xaxis,yaxis;
		
	xaxis.x = star->origin.x + star->xaxis.x;
	xaxis.y = star->origin.y + star->xaxis.y;
	xaxis.z = star->origin.z + star->xaxis.z;
	
	yaxis.x = star->origin.x + star->yaxis.x;
	yaxis.y = star->origin.y + star->yaxis.y;
	yaxis.z = star->origin.z + star->yaxis.z;
	
	plugin_stuff.math_funcs.fz_math_3d_map_plane_from_pts(&xaxis, &star->origin, &yaxis, plane);
}


/************************************************************************
	Star otype uuid callback function
*************************************************************************/
static fzrt_error_td star_otyp_uuid(
	fzrt_UUID_td			uuid 		
	)
{

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

/************************************************************************
	Star otype info callback function
*************************************************************************/
static fzrt_error_td star_otyp_info(
	fzrt_int					*size,
	fzrt_int					*flags
	)
{

	*size  = sizeof(star_otyp_parms_td);
	*flags = 0;
	FZ_SETBIT(*flags,FZ_OTYP_ALWAYS_FACET);
	FZ_SETBIT(*flags,FZ_OTYP_HANDLE_RVRS);
	return(FZRT_NOERR);
}

/************************************************************************
	Star init callback function
*************************************************************************/
static fzrt_error_td star_otyp_init(
	fzrt_int			windex,
	fz_objt_ptr	objt,
	fzrt_ptr		parm
	)
{
	star_otyp_parms_td		*parms_ptr;
	fzrt_error_td			err = FZRT_NOERR;
	
	if(parm != NULL)
	{
		parms_ptr = (star_otyp_parms_td *)parm;

		parms_ptr->base_type = 2 /*_star_tool_opts->base_type*/;
		
		parms_ptr->origin.x = 0.0;
		parms_ptr->origin.y = 0.0;
		parms_ptr->origin.z = 0.0;
		
		parms_ptr->xaxis.x = 1.0;
		parms_ptr->xaxis.y = 0.0;
		parms_ptr->xaxis.z = 0.0;
		parms_ptr->yaxis.x = 0.0;
		parms_ptr->yaxis.y = 1.0;
		parms_ptr->yaxis.z = 0.0;
		
		parms_ptr->radius    = 96.0 /*_star_tool_opts->radius*/;
		parms_ptr->rad_ratio = 0.5 /*_star_tool_opts->rad_ratio*/;
	}

	return(err);
}

/************************************************************************
	Star finit callback function
*************************************************************************/
static fzrt_error_td star_otyp_finit (
	fzrt_int			windex,
	fz_objt_ptr		objt,
	fzrt_ptr		parm
	)
{
	return(FZRT_NOERR);
}

/************************************************************************
	Star name callback function
*************************************************************************/
static fzrt_error_td star_otyp_name(
	fzrt_int			windex,		
	fz_objt_ptr	objt,
	fzrt_ptr		parm,		
	char			*str,
	fzrt_int			max_str
	)
{
	if(str) 
	{	plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, STAR_STR_ID, STAR_STR_OTYP_NAME, str);
	}
	return(FZRT_NOERR);
}

/************************************************************************
	Star transform callback function
*************************************************************************/
static fzrt_error_td star_otyp_tform(
	fzrt_int			windex,
	fz_objt_ptr	objt,
	fzrt_ptr		parm,
	fz_mat4x4_td	*tform
	)
{
	star_otyp_parms_td			*parms_ptr;
	fz_xyz_td					xaxis,yaxis,scl;
	fzrt_error_td				rv = FZRT_NOERR;
	
	if(parm != NULL)
	{
		parms_ptr = (star_otyp_parms_td *)parm;

		plugin_stuff.math_funcs.fz_math_4x4_mat_to_trl_scl_rot(tform,NULL,&scl,NULL);

		xaxis.x = parms_ptr->origin.x + parms_ptr->xaxis.x;
		xaxis.y = parms_ptr->origin.y + parms_ptr->xaxis.y;
		xaxis.z = parms_ptr->origin.z + parms_ptr->xaxis.z;
		
		yaxis.x = parms_ptr->origin.x + parms_ptr->yaxis.x;
		yaxis.y = parms_ptr->origin.y + parms_ptr->yaxis.y;
		yaxis.z = parms_ptr->origin.z + parms_ptr->yaxis.z;

		plugin_stuff.math_funcs.fz_math_4x4_multiply_mat_xyz(tform, &parms_ptr->origin);
		plugin_stuff.math_funcs.fz_math_4x4_multiply_mat_xyz(tform, &xaxis);
		plugin_stuff.math_funcs.fz_math_4x4_multiply_mat_xyz(tform, &yaxis);
		
		plugin_stuff.math_funcs.fz_math_3d_create_unit_vec(&parms_ptr->origin,&xaxis,&parms_ptr->xaxis);
		plugin_stuff.math_funcs.fz_math_3d_create_unit_vec(&parms_ptr->origin,&yaxis,&parms_ptr->yaxis);
		
		parms_ptr->radius *= scl.x;
	}
	
	return(rv);
}


/************************************************************************
	Star geometry callback function
*************************************************************************/
static fzrt_error_td star_otyp_geom(
	fzrt_int					windex,			
	fz_objt_ptr				obj,			
	fzrt_ptr				parm,			
	fz_map_plane_td 		*plane,			
	fz_xyz_td				*center,		
	fz_xyz_mm_td			*bbox			
	)
{
	star_otyp_parms_td			*parms_ptr;
	fzrt_error_td				err = FZRT_NOERR;

	if(parm != NULL)
	{
		parms_ptr = (star_otyp_parms_td*) parm;
		
		if ( plane ) 
		{	
			star_otyp_get_mplane(parms_ptr,plane);
		}

		if(center)
		{
			center->x = 0.0;
			center->y = 0.0;
			center->z = 0.0;
		}

		if(bbox)
		{
			bbox->xmin = bbox->ymin = bbox->zmin = -parms_ptr->radius;
			bbox->xmax = bbox->ymax = bbox->zmax =  parms_ptr->radius;
		}
	}

	return(err);
}

#define	START_RATIO_MIN 0.1
#define	START_RATIO_MAX 0.9
/************************************************************************
	Star regen callback function
*************************************************************************/
static fzrt_error_td star_otyp_regen(
	fzrt_int				windex,
	fz_objt_ptr			obj,	
	fzrt_ptr			parm	
	)
{
	fzrt_error_td				rv = FZRT_NOERR;
	fz_xyz_td					rxyz,rot,pnt,vec;
	double						radius;
	fzrt_int						i,n,ncord,nsegt,ncurv,nface,ncord2,nsegt2,ncurv2,nface2;
	fzrt_int						sindx,shead,snext,pindx[3],lval;
	fz_map_plane_td				local_mplane;
	fz_objt_ptr					temp_obj;
	fz_objt_spid_type_enum		spid_type;
	fz_objt_spid_cnstr_opts_ptr	spid_opts;
	fz_type_td					data;
	fzrt_boolean				bval;
	
	star_otyp_parms_td			*star;

	if(parm != NULL)
	{
		star = (star_otyp_parms_td *)parm;
		
		star_otyp_get_mplane(star,&local_mplane);
		plugin_stuff.model_funcs.fz_objt_fact_reset(windex, obj);

		plugin_stuff.math_funcs.fz_math_3d_vec_rotation_xyz(&star->xaxis,&star->yaxis,&rot);

		radius = star->radius * (START_RATIO_MIN + star->rad_ratio * (START_RATIO_MAX - START_RATIO_MIN));
		rxyz.x = radius;
		rxyz.y = radius;
		rxyz.z = radius;
		spid_opts = NULL;
		
		switch ( star->base_type )
		{
			case 0 : spid_type = FZ_OBJT_SPID_TYPE_TETRA;		break;
			case 1 : spid_type = FZ_OBJT_SPID_TYPE_HEXA;		break;
			case 2 : spid_type = FZ_OBJT_SPID_TYPE_OCTA;		break;
			case 3 : spid_type = FZ_OBJT_SPID_TYPE_DODECA;	break;
			case 4 : spid_type = FZ_OBJT_SPID_TYPE_ICOSA;		break;
			case 5 : spid_type = FZ_OBJT_SPID_TYPE_SOCCER;	break;
			case 6 : 
			case 7 : 
				spid_type = FZ_OBJT_SPID_TYPE_GEO;
				plugin_stuff.model_funcs.fz_objt_cnstr_spid_opts_init(windex,&spid_opts);
				if ( star->base_type == 6 )	lval = 2;
				else						lval = 4;
				plugin_stuff.type_funcs.fz_type_set_int(&lval, &data);
				plugin_stuff.model_funcs.fz_objt_cnstr_spid_opts_set(windex,spid_opts,FZ_OBJT_SPID_PARM_GEO_NUM_SUBDIV,&data);
				bval = TRUE;
				plugin_stuff.type_funcs.fz_type_set_boolean(&bval, &data);
				plugin_stuff.model_funcs.fz_objt_cnstr_spid_opts_set(windex,spid_opts,FZ_OBJT_SPID_PARM_GEO_BY_LEVEL,&data);
			break;
		
		}
		
		if((rv = plugin_stuff.model_funcs.fz_objt_cnstr_spid(windex,&rxyz,spid_type,&star->origin,&rot,spid_opts,&temp_obj)) == FZRT_NOERR)
		{
			
			plugin_stuff.model_funcs.fz_objt_get_face_count(windex,temp_obj,FZ_OBJT_MODEL_TYPE_FACT,&nface);
			plugin_stuff.model_funcs.fz_objt_get_curv_count(windex,temp_obj,FZ_OBJT_MODEL_TYPE_FACT,&ncurv);
			plugin_stuff.model_funcs.fz_objt_get_segt_count(windex,temp_obj,FZ_OBJT_MODEL_TYPE_FACT,&nsegt);
			plugin_stuff.model_funcs.fz_objt_get_point_count(windex,temp_obj,FZ_OBJT_MODEL_TYPE_FACT,&ncord);
			
			ncord2 = ncord + nface;
			ncurv2 = 0;
			nface2 = 0;
			nsegt2 = 0;
			for(i = 0; i < ncurv; i++)
			{
				plugin_stuff.model_funcs.fz_objt_curv_get_segt_count(windex,temp_obj,i,FZ_OBJT_MODEL_TYPE_FACT,&n);
				ncurv2 +=  n;
				nface2 +=  n;
				nsegt2 +=  n * 3;
			}
		
			if((rv = plugin_stuff.model_funcs.fz_objt_fact_allocate(windex,obj,nface2,ncurv2,nsegt2,ncord2)) == FZRT_NOERR )
			{
				/* COPY SPHEROID POINTS */
				for(i = 0; i < ncord; i++)
				{	plugin_stuff.model_funcs.fz_objt_point_get_xyz(windex,temp_obj,i,FZ_OBJT_MODEL_TYPE_FACT,&pnt);
					plugin_stuff.model_funcs.fz_objt_fact_add_pnts(windex,obj,&pnt,1);
				}
				
				/* CREATE STAR TIP POINTS */
				radius = star->radius - radius;
				for(i = 0; i < nface; i++)
				{
					plugin_stuff.model_funcs.fz_objt_alys_get_face_cog(windex,temp_obj,i,FZ_OBJT_MODEL_TYPE_FACT,&pnt);
					plugin_stuff.math_funcs.fz_math_3d_create_unit_vec(&star->origin,&pnt,&vec);
					pnt.x += vec.x * radius;
					pnt.y += vec.y * radius;
					pnt.z += vec.z * radius;
					plugin_stuff.model_funcs.fz_objt_fact_add_pnts(windex,obj,&pnt,1);
				}
				
				/* CREATE FACES */
				for(i = 0; i < ncurv; i++)
				{
					plugin_stuff.model_funcs.fz_objt_curv_get_segt_count(windex,temp_obj,i,FZ_OBJT_MODEL_TYPE_FACT,&n);
					
					plugin_stuff.model_funcs.fz_objt_curv_get_sindx(windex,temp_obj,i,FZ_OBJT_MODEL_TYPE_FACT,&shead);
					sindx = shead;
					do
					{
						plugin_stuff.model_funcs.fz_objt_segt_get_next(windex,temp_obj,sindx,FZ_OBJT_MODEL_TYPE_FACT,&snext);
						
						plugin_stuff.model_funcs.fz_objt_segt_get_start_pindx(windex,temp_obj,sindx,FZ_OBJT_MODEL_TYPE_FACT,&pindx[0]);
						plugin_stuff.model_funcs.fz_objt_segt_get_end_pindx(windex,temp_obj,sindx,FZ_OBJT_MODEL_TYPE_FACT,&pindx[1]);
						pindx[2] = ncord + i;
						
						plugin_stuff.model_funcs.fz_objt_fact_create_face(windex,obj,pindx,3,NULL);
						
					} while ((sindx = snext) != shead );
				}
				
				/* LINK FACES */
				plugin_stuff.model_funcs.fz_objt_fact_link_faces(windex,obj);
			}
		
			if (spid_opts) plugin_stuff.model_funcs.fz_objt_cnstr_spid_opts_finit(windex,&spid_opts);

			plugin_stuff.model_funcs.fz_objt_edit_delete_objt(windex, temp_obj);
		}
	}

	return(rv);
}


enum
{
	STAR_OTYP_STACK_PVIEW_DATA = 0,
	STAR_OTYP_STACK_PVIEW_OPTS,
	
	STAR_OTYP_STACK_PVIEW_MAX
};

typedef struct star_otyp_pview_data_td
{	
	fzrt_int			src_windex;
	fzrt_int			dst_windex;
	fz_objt_ptr		src_obj;
	fz_objt_ptr		dst_obj;
	star_otyp_parms_td	star_parms;
} star_otyp_pview_data_td;

/************************************************************************
	load callback function for the 3d preview of the star object
*************************************************************************/
static fzrt_error_td star_otyp_fuim_load_func(fz_fuim_tmpl_ptr fuim_tmpl, fzrt_int src_windex, fzrt_int dst_windex)
{
	fzrt_error_td			err=FZRT_NOERR;
	star_otyp_pview_data_td	*pview_data;

	/* begin execution */

	plugin_stuff.fuim_funcs.fz_fuim_stack_get_ptr(fuim_tmpl, STAR_OTYP_STACK_PVIEW_DATA, (void**)&pview_data);

	if(pview_data->src_obj != NULL)
	{	
		pview_data->dst_windex = dst_windex;

		if((err = plugin_stuff.model_funcs.fz_objt_edit_copy_objt_to_windex(src_windex,pview_data->src_obj,dst_windex, TRUE, &pview_data->dst_obj)) == FZRT_NOERR )
			err = plugin_stuff.model_funcs.fz_objt_add_objt_to_project(dst_windex,pview_data->dst_obj);
	}
	
	return(err);
}

/************************************************************************
	new value callback function for the star object edit dialog
*************************************************************************/
static fzrt_boolean star_otyp_fuim_newval(fz_fuim_tmpl_ptr fuim_tmpl, void *data_ptr)
{
	star_otyp_pview_data_td	*pview_data;
	star_otyp_parms_td		*parm_data;
	
	plugin_stuff.fuim_funcs.fz_fuim_stack_get_ptr(fuim_tmpl, STAR_OTYP_STACK_PVIEW_DATA, (void**)&pview_data);

	plugin_stuff.model_funcs.fz_objt_parm_get_data(pview_data->dst_windex,pview_data->dst_obj,(fzrt_ptr*)&parm_data);
	*parm_data = pview_data->star_parms;
	
	plugin_stuff.model_funcs.fz_objt_edit_parm_regen(pview_data->dst_windex,pview_data->dst_obj);
	
	return (TRUE);
}

/************************************************************************
	reset callback function for the star object edit dialog
*************************************************************************/
static fzrt_boolean  star_otyp_fuim_reset(fz_fuim_tmpl_ptr fuim_tmpl, void *data_ptr)
{
	star_otyp_pview_data_td		*pview_data;

	plugin_stuff.fuim_funcs.fz_fuim_stack_get_ptr(fuim_tmpl, STAR_OTYP_STACK_PVIEW_DATA, (void**)&pview_data);

	return(TRUE);
}

/************************************************************************
	OK callback function for the star object edit dialog
*************************************************************************/
static fzrt_boolean star_otyp_fuim_ok(fz_fuim_tmpl_ptr fuim_tmpl, void *data_ptr)
{
	star_otyp_pview_data_td		*pview_data;

	plugin_stuff.fuim_funcs.fz_fuim_stack_get_ptr(fuim_tmpl, STAR_OTYP_STACK_PVIEW_DATA, (void**)&pview_data);

	star_otyp_fuim_newval(fuim_tmpl, data_ptr);
	
	plugin_stuff.model_funcs.fz_objt_edit_copy_objt_data_to_windex(pview_data->dst_windex,
		pview_data->dst_obj, pview_data->src_windex,
		pview_data->src_obj, TRUE);

	return(TRUE);
}


/************************************************************************
	Star edit callback function
*************************************************************************/
static fzrt_error_td	star_otyp_iface_tmpl(
	fzrt_int					windex,
	fz_fuim_tmpl_ptr		fuim_tmpl,
	fzrt_ptr				objt_ptr
	)
{
	fzrt_error_td			err = FZRT_NOERR;
	short					g1,g2,g3;
	char					str[256];
	fz_objt_ptr				obj;
	star_otyp_parms_td		*star;
	fz_fuim_pview_opts_ptr	pview_opts;
	star_otyp_pview_data_td	pview_data,*pview_data_ptr;
	fzrt_menu_ptr			menu;
	fz_tag_td				obj_tag;
	
	obj = (fz_objt_ptr)objt_ptr;
	plugin_stuff.model_funcs.fz_objt_ptr_to_tag(windex, obj,&obj_tag);
	plugin_stuff.model_funcs.fz_objt_parm_get_data(windex,obj,(fzrt_ptr*)&star);

	plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, STAR_STR_ID, STAR_STR_EDIT_TITLE, str);
	if((err = plugin_stuff.fuim_funcs.fz_fuim_tmpl_init(fuim_tmpl, str, 0, STAR_OTYP_ID, 0)) == FZRT_NOERR)
	{
		pview_data.src_obj = obj;
		pview_data.dst_obj = NULL;
		pview_data.src_windex = windex;
		pview_data.dst_windex = -1;
		pview_data.star_parms = *star;
	
		plugin_stuff.fuim_funcs.fz_fuim_tmpl_set_new_value_func(fuim_tmpl, star_otyp_fuim_newval, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_tmpl_set_ok_func(fuim_tmpl,star_otyp_fuim_ok, NULL);
		plugin_stuff.fuim_funcs.fz_fuim_tmpl_set_reset_func(fuim_tmpl, star_otyp_fuim_reset, NULL);

		g1 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, -1, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ|FZ_FUIM_FLAG_GFLT, 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_pview_opts_init(&pview_opts,windex); 
				plugin_stuff.fuim_funcs.fz_fuim_pview_opts_set_load_func(pview_opts, star_otyp_fuim_load_func);
				plugin_stuff.fuim_funcs.fz_fuim_pview_create(fuim_tmpl, g2, FZ_FUIM_NONE, pview_opts);
				plugin_stuff.fuim_funcs.fz_fuim_stack_put(fuim_tmpl, STAR_OTYP_STACK_PVIEW_DATA, sizeof(pview_data), &pview_data);
				plugin_stuff.fuim_funcs.fz_fuim_stack_put(fuim_tmpl, STAR_OTYP_STACK_PVIEW_OPTS, sizeof(pview_opts), &pview_opts);
				plugin_stuff.fuim_funcs.fz_fuim_stack_get_ptr(fuim_tmpl, STAR_OTYP_STACK_PVIEW_DATA, (void**)&pview_data_ptr);
				star = &pview_data_ptr->star_parms;

			g2 = plugin_stuff.fuim_funcs.fz_fuim_new_group(fuim_tmpl, g1, FZ_FUIM_NONE, FZ_FUIM_FLAG_NONE, NULL);
			
			plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_menu(plugin_stuff.fz_rsrc_ref_func, STAR_BASE_MENU_ID,&menu);
			plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, STAR_STR_ID, STAR_STR_BASE_TYPE, str);
//			g3 = plugin_stuff.fuim_funcs.fz_fuim_new_menu(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, str, menu, FALSE, NULL, NULL);
			g3 = plugin_stuff.fuim_funcs.fz_fuim_new_menu_anim(fuim_tmpl, g2, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, str, menu, FALSE, NULL, NULL,
															   0,windex,FZ_FUIM_ANIM_OBJECT_TYPE,&obj_tag,STAR_PARM_BASE_TYPE_UUID);
				plugin_stuff.fuim_funcs.fz_fuim_item_range_int(fuim_tmpl,g3, &star->base_type, 0, 7, FZ_FUIM_FORMAT_INT_DEFAULT,
									  FZ_FUIM_RANGE_MIN | FZ_FUIM_RANGE_MAX | FZ_FUIM_RANGE_MIN_INCL | FZ_FUIM_RANGE_MAX_INCL);
			
			plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, STAR_STR_ID, STAR_STR_RADIUS, str);
//			plugin_stuff.fuim_funcs.fz_fuim_new_text_static_edit(fuim_tmpl,g2,FZ_FUIM_NONE,str,FZ_FUIM_NONE,FZ_FUIM_FLAG_NONE, NULL, NULL,&g3);			
			plugin_stuff.fuim_funcs.fz_fuim_new_text_static_edit_anim(fuim_tmpl,g2,FZ_FUIM_NONE,str,FZ_FUIM_NONE,FZ_FUIM_FLAG_NONE, NULL, NULL,
																	  0,windex,FZ_FUIM_ANIM_OBJECT_TYPE,&obj_tag,STAR_PARM_RADIUS_UUID,&g3);			
			plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, g3, &star->radius, 0.0, 0.0, FZ_FUIM_FORMAT_FLOAT_DISTANCE, FZ_FUIM_RANGE_MIN);
			
			plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, STAR_STR_ID, STAR_STR_RAY_RATIO, str);
/*			plugin_stuff.fuim_funcs.fz_fuim_new_slid_edit_pcent_double(
					fuim_tmpl, 
					g2,
					str,
					FZ_FUIM_NONE,
					FZ_FUIM_NONE,
					0.0,
					1.0,
					0.0,
					100.0,
					FZ_FUIM_RANGE_MIN | FZ_FUIM_RANGE_MIN_INCL | FZ_FUIM_RANGE_MAX | FZ_FUIM_RANGE_MAX_INCL,
					NULL,
					&star->rad_ratio, 
					NULL,
					NULL);	*/
			plugin_stuff.fuim_funcs.fz_fuim_new_slider_edit_pcent_double_anim(
					fuim_tmpl, 
					g2,
					str,
					FZ_FUIM_NONE,
					FZ_FUIM_NONE,
					0.0,
					1.0,
					0.0,
					100.0,
					0.0,
					100.0,
					FZ_FUIM_RANGE_MIN | FZ_FUIM_RANGE_MIN_INCL | FZ_FUIM_RANGE_MAX | FZ_FUIM_RANGE_MAX_INCL,
					NULL,
					NULL,
					&star->rad_ratio,
					0,windex,FZ_FUIM_ANIM_OBJECT_TYPE,&obj_tag,STAR_PARM_RAY_RATIO_UUID,
					NULL,
					NULL);
			
	}
	
	return (err);
}

/************************************************************************
	Star get key points callback function
*************************************************************************/
static fzrt_error_td star_otyp_get_key_pnts(
	fzrt_int				windex,		
	fz_objt_ptr			obj,			
	fzrt_ptr			parm,			
	fzrt_int				*knt,			
	fz_xyz_td			*pnts			
	)
{
	fzrt_error_td		err = FZRT_NOERR;
	star_otyp_parms_td	*parms_ptr;
	fz_map_plane_td	local_mplane;
	
	if(knt) *knt = 1;
	
	if(pnts && parm)
	{
		parms_ptr = (star_otyp_parms_td*) parm;
		
		star_otyp_get_mplane(parms_ptr,&local_mplane);

		pnts[0].x = 0.0;
		pnts[0].y = 0.0;
		pnts[0].z = 0.0;

		plugin_stuff.math_funcs.fz_math_3d_map_plane_to_world(&local_mplane, &pnts[0]);
	}

	return(err);
}


/************************************************************************
	Star io stream callback function
*************************************************************************/
static fzrt_error_td star_otyp_iost(	
	fzrt_int					windex,			
	fz_objt_ptr				obj,			
	fzrt_ptr				parm,			
	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;
	star_otyp_parms_td	*parms_ptr;

	parms_ptr = (star_otyp_parms_td *)parm;

	if ( dir == FZ_IOST_WRITE ) *version = 0;
	
	if((err = plugin_stuff.iost_funcs.fz_iost_int(iost,&parms_ptr->base_type,1))	== FZRT_NOERR &&
	   (err = plugin_stuff.iost_funcs.fz_iost_xyz(iost,&parms_ptr->origin,1)) 		== FZRT_NOERR &&
	   (err = plugin_stuff.iost_funcs.fz_iost_xyz(iost,&parms_ptr->xaxis,1)) 		== FZRT_NOERR &&
	   (err = plugin_stuff.iost_funcs.fz_iost_xyz(iost,&parms_ptr->yaxis,1)) 		== FZRT_NOERR &&
	   (err = plugin_stuff.iost_funcs.fz_iost_double(iost,&parms_ptr->radius,1)) 	== FZRT_NOERR )
	{	err = plugin_stuff.iost_funcs.fz_iost_double(iost,&parms_ptr->rad_ratio,1);
	}

	return(err);
}

/************************************************************************
	Callbacks that provide information about this object type's
	parameters.  These callbacks are useful, in particular, for object
	animation allowing formZ to query/change the parameters that can be
	animated.
*************************************************************************/

enum
{
	STAR_PARM_BASE_TYPE,
	STAR_PARM_RADIUS,
	STAR_PARM_RAY_RATIO,
	
	STAR_PARM_MAX
};

/************************************************************************
	parameter count callback function
*************************************************************************/
static fzrt_error_td star_parm_count(
	fzrt_int			*count	
	)
{
	fzrt_error_td err = FZRT_NOERR;
	
	*count = STAR_PARM_MAX;
	
	return err;
}

/************************************************************************
	parameter get info callback function
*************************************************************************/
static fzrt_error_td  star_parm_get_info(
	fzrt_int						parm_indx,			
	fzrt_UUID_td				parm_uuid,			
	fz_string_td				parm_name,			
	fz_type_enum				*parm_type,			
	fz_fuim_format_int_enum		*parm_format_int,	
	fz_fuim_format_float_enum	*parm_format_float,	
	fz_fuim_item_type_enum		*parm_fuim_item,
	fzrt_int						*parm_range,		
	fz_type_td					*parm_range_min,	
	fz_type_td					*parm_range_max,	
	fzrt_int						*flags				
	)
{
	fzrt_error_td	err = FZRT_NOERR;
	char			str[256];
	fzrt_int			lval;
	double			dval;
	
	switch(parm_indx)
	{
		case STAR_PARM_BASE_TYPE:
			if (parm_uuid)
				plugin_stuff.fzrt_base_funcs.fzrt_UUID_copy(STAR_PARM_BASE_TYPE_UUID, parm_uuid);
			if (parm_name)
			{
				plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, STAR_STR_ID, STAR_STR_BASE_TYPE, str);
				strcpy(parm_name, str);
			}
			if (parm_type)
				*parm_type = FZ_TYPE_INT;
			if (parm_format_int)
				*parm_format_int = FZ_FUIM_FORMAT_INT_DEFAULT;
			if (parm_format_float)
				*parm_format_float = FZ_FUIM_FORMAT_FLOAT_DEFAULT;
			if (parm_range)
				*parm_range = FZ_FUIM_RANGE_MIN | FZ_FUIM_RANGE_MIN_INCL | FZ_FUIM_RANGE_MAX | FZ_FUIM_RANGE_MAX_INCL;
			if (parm_range_min)
			{
				lval = 0;
				plugin_stuff.type_funcs.fz_type_set_int(&lval, parm_range_min);
			}
			if (parm_range_max)
			{
				lval = 7;
				plugin_stuff.type_funcs.fz_type_set_int(&lval, parm_range_max);
			}
			if (flags)
			{	*flags = 0;
				FZ_SETBIT(*flags,FZ_OTYP_PARM_ANIM_LEVEL2_BIT);
			}
			if ( parm_fuim_item ) *parm_fuim_item = FZ_FUIM_ITEM_MENU;
		break;
		
		case STAR_PARM_RADIUS:
			if (parm_uuid)
				plugin_stuff.fzrt_base_funcs.fzrt_UUID_copy(STAR_PARM_RADIUS_UUID, parm_uuid);
			if (parm_name)
			{
				plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, STAR_STR_ID, STAR_STR_RADIUS, str);
				strcpy(parm_name, str);
			}
			if (parm_type)
				*parm_type = FZ_TYPE_DOUBLE;
			if (parm_format_int)
				*parm_format_int = FZ_FUIM_FORMAT_INT_DEFAULT;
			if (parm_format_float)
				*parm_format_float = FZ_FUIM_FORMAT_FLOAT_DISTANCE;
			if (parm_range)
				*parm_range = FZ_FUIM_RANGE_MIN;
			if (parm_range_min)
			{
				dval = 0;
				plugin_stuff.type_funcs.fz_type_set_double(&dval, parm_range_min);
			}
			if (flags)
			{	*flags = 0;
				FZ_SETBIT(*flags,FZ_OTYP_PARM_ANIM_LEVEL1_BIT);
			}
			if ( parm_fuim_item ) *parm_fuim_item = FZ_FUIM_ITEM_TEXT;
		break;
		
		case STAR_PARM_RAY_RATIO:
			if (parm_uuid)
				plugin_stuff.fzrt_base_funcs.fzrt_UUID_copy(STAR_PARM_RAY_RATIO_UUID, parm_uuid);
			if (parm_name)
			{
				plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, STAR_STR_ID, STAR_STR_RAY_RATIO, str);
				strcpy(parm_name, str);
			}
			if (parm_type)
				*parm_type = FZ_TYPE_DOUBLE;
			if (parm_format_int)
				*parm_format_int = FZ_FUIM_FORMAT_INT_DEFAULT;
			if (parm_format_float)
				*parm_format_float = FZ_FUIM_FORMAT_FLOAT_PERCENT;
			if (parm_range)
				*parm_range = FZ_FUIM_RANGE_MIN | FZ_FUIM_RANGE_MIN_INCL | FZ_FUIM_RANGE_MAX | FZ_FUIM_RANGE_MAX_INCL;
			if (parm_range_min)
			{
				dval = 0;
				plugin_stuff.type_funcs.fz_type_set_double(&dval, parm_range_min);
			}
			if (parm_range_max)
			{
				dval = 1;
				plugin_stuff.type_funcs.fz_type_set_double(&dval, parm_range_max);
			}
			if (flags)
			{	*flags = 0;
				FZ_SETBIT(*flags,FZ_OTYP_PARM_ANIM_LEVEL1_BIT);
			}
			if ( parm_fuim_item ) *parm_fuim_item = FZ_FUIM_ITEM_SLIDER_TEXT;
		break;
	}
	
	return err;
}

/************************************************************************
	parameter get state str callback function
*************************************************************************/
static fzrt_error_td  star_parm_get_state_str(
	fzrt_UUID_td		parm_uuid,	
	fzrt_int				which_state,
	fz_string_td		str			
	)
{
	fzrt_error_td	err = FZRT_NOERR;
	fzrt_menu_ptr	menu;

	if (plugin_stuff.fzrt_base_funcs.fzrt_UUID_is_equal(parm_uuid, STAR_PARM_BASE_TYPE_UUID))
	{
		if (which_state >= 0)
		{
			plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_menu(plugin_stuff.fz_rsrc_ref_func, STAR_BASE_MENU_ID,&menu);
			err = plugin_stuff.fzrt_ui_funcs.fzrt_menu_get_item_text(menu, which_state+1/*1-based*/, str);
		}
	}
	else
		err = plugin_stuff.fzrt_base_funcs.fzrt_error_set(FZRT_BAD_PARAM_ERROR, FZRT_ERROR_SEVERITY_ERROR,FZRT_ERROR_CONTEXT_PLUGIN, 0);
	
	return err;
}
	

/************************************************************************
	parameter get callback function
*************************************************************************/
static fzrt_error_td  star_parm_get(
	fzrt_int				windex,		
	fz_objt_ptr			objt,		
	fzrt_UUID_td		parm_uuid,
	fz_type_td			*data		
	)
{
	fzrt_error_td			err = FZRT_NOERR;
	star_otyp_parms_td		*star;
	fzrt_int					lval;
	double					dval;

	plugin_stuff.model_funcs.fz_objt_parm_get_data(windex,objt,(fzrt_ptr*)&star);

	if (plugin_stuff.fzrt_base_funcs.fzrt_UUID_is_equal(parm_uuid, STAR_PARM_BASE_TYPE_UUID))
	{
		lval = star->base_type;
		plugin_stuff.type_funcs.fz_type_set_int(&lval, data);
	}
	else if (plugin_stuff.fzrt_base_funcs.fzrt_UUID_is_equal(parm_uuid, STAR_PARM_RADIUS_UUID))
	{
		dval = star->radius;
		plugin_stuff.type_funcs.fz_type_set_double(&dval, data);
	}
	else if (plugin_stuff.fzrt_base_funcs.fzrt_UUID_is_equal(parm_uuid, STAR_PARM_RAY_RATIO_UUID))
	{
		dval = star->rad_ratio;
		plugin_stuff.type_funcs.fz_type_set_double(&dval, data);
	}
	else
		err = plugin_stuff.fzrt_base_funcs.fzrt_error_set(FZRT_BAD_PARAM_ERROR, FZRT_ERROR_SEVERITY_ERROR,FZRT_ERROR_CONTEXT_PLUGIN, 0);
	
	return err;
}
	

/************************************************************************
	parameter set callback function
*************************************************************************/
static fzrt_error_td  star_parm_set(
	fzrt_int				windex,		
	fz_objt_ptr			objt,		
	fzrt_UUID_td		parm_uuid,
	fz_type_td			*data		
	)
{
	fzrt_error_td			err = FZRT_NOERR;
	star_otyp_parms_td		*star;
	fzrt_int					lval;
	double					dval;

	plugin_stuff.model_funcs.fz_objt_parm_get_data(windex,objt,(fzrt_ptr*)&star);

	if (plugin_stuff.fzrt_base_funcs.fzrt_UUID_is_equal(parm_uuid, STAR_PARM_BASE_TYPE_UUID))
	{
		plugin_stuff.type_funcs.fz_type_get_int(data, &lval);
		if (lval >= 0 && lval <= 7)
			star->base_type = lval;
		else
			err = -1;
	}
	else if (plugin_stuff.fzrt_base_funcs.fzrt_UUID_is_equal(parm_uuid, STAR_PARM_RADIUS_UUID))
	{
		plugin_stuff.type_funcs.fz_type_get_double(data, &dval);
		if (dval > 0)
			star->radius = dval;
		else
			err = -1;
	}
	else if (plugin_stuff.fzrt_base_funcs.fzrt_UUID_is_equal(parm_uuid, STAR_PARM_RAY_RATIO_UUID))
	{
		plugin_stuff.type_funcs.fz_type_get_double(data, &dval);
		if (dval >= 0.0 && dval <= 1.0)
			star->rad_ratio = dval;
		else
			err = -1;
	}
	else
		err = -1;
	
	if (err == -1)
		err = plugin_stuff.fzrt_base_funcs.fzrt_error_set(FZRT_BAD_PARAM_ERROR, FZRT_ERROR_SEVERITY_ERROR,FZRT_ERROR_CONTEXT_PLUGIN, 0);
	
	return err;
}
	

#define FUIM_STAR_STACK_UUID "\x56\xf8\x38\x9b\x5e\x9b\x41\x05\x90\x4b\xc9\x8a\xc9\x88\x69\xed"
enum
{
	FUIM_STAR_STACK_OBJT_LIST = 0,
	FUIM_STAR_STACK_NOBJT,
	FUIM_STAR_STACK_WINDEX,
	
	FUIM_STAR_STACK_MAX
};

enum
{
	STAR_ID_RADIUS = 0,
	STAR_ID_RATIO_SLIDER,
	STAR_ID_RATIO_TEXT,
	STAR_ID_BASE_TYPE,
	STAR_ID_MAX
};

static fzrt_int	_fuim_star_ids[STAR_ID_MAX];

/************************************************************************
	item callback for multi editing
*************************************************************************/
static short fuim_star_multi_item_func(fz_fuim_tmpl_ptr fuim_tmpl, fzrt_int action, short item_id, void *func_data, fz_fuim_type_td *rv_data)
{
	fz_objt_ptr			*objts,obj;
	fzrt_int				i,nobjt,lval,windex;
	double				fval;
	star_otyp_parms_td	*star;
	short				rv = FALSE;
	
	static	fzrt_int	nested = 0;
	
	
	switch (action)
	{
		case FZ_FUIM_ACTN_GET_VALUE:
			plugin_stuff.fuim_funcs.fz_fuim_stack_uuid_get(fuim_tmpl, FUIM_STAR_STACK_UUID, FUIM_STAR_STACK_OBJT_LIST,  &objts);
			plugin_stuff.fuim_funcs.fz_fuim_stack_uuid_get(fuim_tmpl, FUIM_STAR_STACK_UUID, FUIM_STAR_STACK_NOBJT,      &nobjt);
			plugin_stuff.fuim_funcs.fz_fuim_stack_uuid_get(fuim_tmpl, FUIM_STAR_STACK_UUID, FUIM_STAR_STACK_WINDEX,     &windex);

			obj = objts[0];
			plugin_stuff.model_funcs.fz_objt_parm_get_data(windex,obj,(fzrt_ptr*)&star);
			
			if		( item_id == _fuim_star_ids[STAR_ID_RADIUS] )		fval = star->radius;
			else if ( item_id == _fuim_star_ids[STAR_ID_RATIO_SLIDER] )	fval = star->rad_ratio;
			else if ( item_id == _fuim_star_ids[STAR_ID_RATIO_TEXT] )	fval = star->rad_ratio;
			else if ( item_id == _fuim_star_ids[STAR_ID_BASE_TYPE] )	lval = star->base_type;
			
			for(i = 1; i < nobjt; i++)
			{
				obj = objts[i];
				plugin_stuff.model_funcs.fz_objt_parm_get_data(windex,obj,(fzrt_ptr*)&star);
				
				if(( item_id == _fuim_star_ids[STAR_ID_RADIUS] && fabs(fval - star->radius) > FZ_MATH_TOL_LIN  ) ||
				   ( item_id == _fuim_star_ids[STAR_ID_RATIO_SLIDER] && fabs(fval - star->radius) > FZ_MATH_TOL_LIN ) ||
				   ( item_id == _fuim_star_ids[STAR_ID_RATIO_TEXT] && fabs(fval - star->radius) > FZ_MATH_TOL_LIN  ) ||
				   ( item_id == _fuim_star_ids[STAR_ID_BASE_TYPE] && lval != star->base_type  ))
				{
					rv = 0x8000 | TRUE;
					break;
				}
			}
			
		break;
			
		case FZ_FUIM_ACTN_PRE_NEW_VALUE	:
			nested++;
			rv = TRUE;
		break;
			
		case FZ_FUIM_ACTN_POST_NEW_VALUE	:
			nested--;
			rv = TRUE;
		break;
			
		case FZ_FUIM_ACTN_NEW_VALUE:
			
			if ( nested == 1 )
			{
				plugin_stuff.fuim_funcs.fz_fuim_stack_uuid_get(fuim_tmpl, FUIM_STAR_STACK_UUID, FUIM_STAR_STACK_OBJT_LIST,  &objts);
				plugin_stuff.fuim_funcs.fz_fuim_stack_uuid_get(fuim_tmpl, FUIM_STAR_STACK_UUID, FUIM_STAR_STACK_NOBJT,      &nobjt);
				plugin_stuff.fuim_funcs.fz_fuim_stack_uuid_get(fuim_tmpl, FUIM_STAR_STACK_UUID, FUIM_STAR_STACK_WINDEX,     &windex);
				
				obj = objts[0];
				plugin_stuff.model_funcs.fz_objt_parm_get_data(windex,obj,(fzrt_ptr*)&star);
				
				if		( item_id == _fuim_star_ids[STAR_ID_RADIUS] )		fval = star->radius;
				else if ( item_id == _fuim_star_ids[STAR_ID_RATIO_SLIDER] )	fval = star->rad_ratio;
				else if ( item_id == _fuim_star_ids[STAR_ID_RATIO_TEXT] )	fval = star->rad_ratio;
				else if ( item_id == _fuim_star_ids[STAR_ID_BASE_TYPE] )	lval = star->base_type;
				
				for(i = 1; i < nobjt; i++)
				{
					obj = objts[i];
					plugin_stuff.model_funcs.fz_objt_parm_get_data(windex,obj,(fzrt_ptr*)&star);
					
					if		( item_id == _fuim_star_ids[STAR_ID_RADIUS] )		star->radius	= fval;
					else if ( item_id == _fuim_star_ids[STAR_ID_RATIO_SLIDER] ) star->rad_ratio = fval;
					else if ( item_id == _fuim_star_ids[STAR_ID_RATIO_TEXT] )	star->rad_ratio = fval;
					else if ( item_id == _fuim_star_ids[STAR_ID_BASE_TYPE] )	star->base_type = lval;
				}
			}
			rv = TRUE;
		break;
	}
	
	return(rv);
}

/************************************************************************
	Object type parameter edit function
 *************************************************************************/
static fzrt_error_td  star_otyp_prop_palt (
	fzrt_int				windex,		
	fz_objt_ptr			*objts,		
	fzrt_int				nobjt,		
	fz_fuim_tmpl_ptr	fuim_tmpl,	
	short				parent
	)
{
	
	fz_string_td		str;
	short				g3,g4;
	fz_objt_ptr			obj;
	star_otyp_parms_td	*star;
	fzrt_menu_ptr		menu;
	
	obj = objts[0];
	plugin_stuff.model_funcs.fz_objt_parm_get_data(windex,obj,(fzrt_ptr*)&star);
	
	plugin_stuff.fuim_funcs.fz_fuim_stack_uuid_put(fuim_tmpl, FUIM_STAR_STACK_UUID, FUIM_STAR_STACK_OBJT_LIST,  sizeof(objts),	 &objts);
	plugin_stuff.fuim_funcs.fz_fuim_stack_uuid_put(fuim_tmpl, FUIM_STAR_STACK_UUID, FUIM_STAR_STACK_NOBJT,      sizeof(nobjt),    &nobjt);
	plugin_stuff.fuim_funcs.fz_fuim_stack_uuid_put(fuim_tmpl, FUIM_STAR_STACK_UUID, FUIM_STAR_STACK_WINDEX,     sizeof(windex),   &windex);
	
	plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_menu(plugin_stuff.fz_rsrc_ref_func, STAR_BASE_MENU_ID,&menu);
	plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, STAR_STR_ID, STAR_STR_BASE_TYPE, str);
	g3 = plugin_stuff.fuim_funcs.fz_fuim_new_menu(fuim_tmpl, parent, FZ_FUIM_NONE, FZ_FUIM_FLAG_HORZ, str, menu, FALSE, fuim_star_multi_item_func, NULL);
	plugin_stuff.fuim_funcs.fz_fuim_item_range_int(fuim_tmpl,g3, &star->base_type, 0, 7, FZ_FUIM_FORMAT_INT_DEFAULT,
							  FZ_FUIM_RANGE_MIN | FZ_FUIM_RANGE_MAX | FZ_FUIM_RANGE_MIN_INCL | FZ_FUIM_RANGE_MAX_INCL);
			
	_fuim_star_ids[STAR_ID_BASE_TYPE] = g3;


	plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, STAR_STR_ID, STAR_STR_RADIUS, str);
	plugin_stuff.fuim_funcs.fz_fuim_new_text_static_edit(fuim_tmpl,parent,FZ_FUIM_NONE,str,FZ_FUIM_NONE,FZ_FUIM_FLAG_NONE, fuim_star_multi_item_func, NULL,&g3);			
	plugin_stuff.fuim_funcs.fz_fuim_item_range_double(fuim_tmpl, g3, &star->radius, 0.0, 0.0, FZ_FUIM_FORMAT_FLOAT_DISTANCE, FZ_FUIM_RANGE_MIN);
			
	_fuim_star_ids[STAR_ID_RADIUS] = g3;

	plugin_stuff.fzrt_base_funcs.fzrt_fzr_get_string(plugin_stuff.fz_rsrc_ref_func, STAR_STR_ID, STAR_STR_RAY_RATIO, str);
	plugin_stuff.fuim_funcs.fz_fuim_new_slid_edit_pcent_double(
			fuim_tmpl, 
			parent,
			str,
			FZ_FUIM_NONE,
			FZ_FUIM_NONE,
			0.0,
			1.0,
			0.0,
			100.0,
			FZ_FUIM_RANGE_MIN | FZ_FUIM_RANGE_MIN_INCL | FZ_FUIM_RANGE_MAX | FZ_FUIM_RANGE_MAX_INCL,
			fuim_star_multi_item_func,
			&star->rad_ratio, 
			&g3,
			&g4);
	_fuim_star_ids[STAR_ID_RATIO_SLIDER] = g3;
	_fuim_star_ids[STAR_ID_RATIO_TEXT] = g4;
	
	return(FZRT_NOERR);
}


/************************************************************************
	Fills the fset structure with the object type callback functions.
*************************************************************************/
fzrt_error_td star_otyp_get_callback_fset ( const fzpl_fset_def_ptr fset_def, fzpl_fset_td * const fset )
{
	fzrt_error_td			err = FZRT_NOERR;
	fz_otyp_cbak_fset		*otyp_fset;

	plugin_stuff.fsf->fzpl_fset_def_check ( 	fset_def, 
										FZ_OTYP_CBAK_FSET_VERSION, 
										FZPL_TYPE_STRING(fz_otyp_cbak_fset), 
										sizeof ( fz_otyp_cbak_fset ), 
										FZPL_VERSION_OP_NEWER );

	if ( err == FZRT_NOERR )
	{
		otyp_fset = (fz_otyp_cbak_fset *)fset;

		otyp_fset->fz_otyp_cbak_name			= star_otyp_name;
		otyp_fset->fz_otyp_cbak_uuid			= star_otyp_uuid;
		otyp_fset->fz_otyp_cbak_info			= star_otyp_info;
		otyp_fset->fz_otyp_cbak_init			= star_otyp_init;
		otyp_fset->fz_otyp_cbak_finit			= star_otyp_finit;
		otyp_fset->fz_otyp_cbak_tform			= star_otyp_tform;
		otyp_fset->fz_otyp_cbak_geom			= star_otyp_geom;
		otyp_fset->fz_otyp_cbak_regen			= star_otyp_regen;
		otyp_fset->fz_otyp_cbak_iface_tmpl		= star_otyp_iface_tmpl;
		otyp_fset->fz_otyp_cbak_get_key_pnts	= star_otyp_get_key_pnts;
		otyp_fset->fz_otyp_cbak_io				= star_otyp_iost;
		otyp_fset->fz_otyp_cbak_parm_count		= star_parm_count;
		otyp_fset->fz_otyp_cbak_parm_get_info2	= star_parm_get_info;
		otyp_fset->fz_otyp_cbak_parm_get_state_str	= star_parm_get_state_str;
		otyp_fset->fz_otyp_cbak_parm_get		= star_parm_get;
		otyp_fset->fz_otyp_cbak_parm_set		= star_parm_set;
		otyp_fset->fz_otyp_cbak_prop_palt		= star_otyp_prop_palt;
	}

	return err;
}
