Useful mxs sdk extension functions

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

REPLY TO THREAD
 
Thread Tools Search this Thread Display Modes
Old 01 January 2013   #1
Useful mxs sdk extension functions

no self respecting maxscripter should be without their own sdk mxs function library. So here's a thread to post those useful functions, speed ups and the like.

So I'll kick off with a few...

def_visible_primitive(sortsf,"sortsf");
     
     struct float_compare 
     {
     	bool operator() (Value *a, Value *b) 
     	{ 
     		return  ascending ? ((Struct*)a)->member_data[index]->to_float() < ((Struct*)b)->member_data[index]->to_float() :
     					((Struct*)a)->member_data[index]->to_float() > ((Struct*)b)->member_data[index]->to_float();
     	}
     	int		index;
     	BOOL	ascending;
     
     	float_compare(int i, BOOL asc = true) : index(i), ascending(asc) {}
     };
     
     //**************************************************  ******************************************
     // sort an array of structs based on the float value in a member field 
     // usage
     // sortsf <array of structs> <#struct_member_name> 
     
     Value* sortsf_cf(Value **arg_list, int count)
     {
     	Array* theArray = (Array*)arg_list[0];

// bum out early if passed and empty array, no need for nasty mxs ** system exception **

	if(theArray->size == 0)  return Integer::intern(0);

     	Struct* theStruct = (Struct*)theArray->data[0];	// use the first array element as the struct "template"
     	Value* temp;
     
     // default to ascending though set if specified by the caller
     
     	BOOL ascending = true;
     	if(count == 3)
     		ascending = arg_list[2]->to_bool();
     
     // gets the member data index from the hash table, return undefined if not present
     
     	if((temp = theStruct->definition->get_member_value(arg_list[1])) == NULL)
     		return &undefined;
     
     // create the sorting compare object with our index
     // this is 1 based but I think max adds a dummy struct member at index 0 so it works
     
     	float_compare compare(temp->to_int(),ascending); 
     
     // sort the array
     
     	std::sort(theArray->data, theArray->data + theArray->size, compare);
     	return Integer::intern(theArray->size);
     }
     
     //**************************************************  ******************************************


Denis has extended it for a more general use here



a couple of silly one that i find useful

def_visible_primitive(itob, "itob");
     def_visible_primitive(btoi, "btoi");
     
   // usage: <BooleanClass>itob <integer>
     Value* itob_cf(Value **arg_list, int count) { return bool_result(arg_list[0]->to_int());}
     
   // usage: <integer>itob <BooleanClass>
     Value* btoi_cf(Value **arg_list, int count) { return Integer::intern(arg_list[0]->to_bool() ? 1 : 0); }

Last edited by Klunk : 01 January 2013 at 12:46 PM.
 
Old 01 January 2013   #2
universal sorter (slightly modifier and extended claude666's code):

  struct prop_float_compare 
  {
  	bool operator() (Value *a, Value *b) 
  	{ 
  		bool result = (a->_get_property(prop)->to_float() < b->_get_property(prop)->to_float());
  		return (reverse) ? !(result) : result;
  	}
  	BOOL reverse;
  	Value* prop;
  	prop_float_compare(Value* i, BOOL reverse = false) : prop(i), reverse(reverse) {}
  };
  struct prop_string_compare 
  {
  	bool operator() (Value *a, Value *b) 
  	{ 
  		bool result = ::_stricmp(a->_get_property(prop)->to_string(), b->_get_property(prop)->to_string()) < 0;
  		return (reverse) ? !(result) : result;
  	}
  	BOOL reverse;
  	Value* prop;
  	prop_string_compare(Value* i, BOOL reverse = false) : prop(i), reverse(reverse) {}
  };
  
     
  def_visible_primitive(sortpv, "sortpv");
  Value* sortpv_cf(Value **arg_list, int count)
  {
  	check_arg_count_with_keys(sortpv, 2, count);
  	Array* theArray = static_cast<Array*>(arg_list[0]);
  	Value* prop = arg_list[1];
  	
  	Value *temp;
  	BOOL reverse = bool_key_arg(flip, temp, false);
  
  	Value* value = (*theArray)[0]->_get_property(prop);
  
  	if(is_float(value) || is_int(value) || is_time(value))
  	{
  		prop_float_compare compare(prop, reverse); 
  		std::sort(theArray->data, theArray->data + theArray->size, compare);
  	}
  	else
  	if(is_string(value) || is_name(value)) 
  	{
  		prop_string_compare compare(prop, reverse); 
  		std::sort(theArray->data, theArray->data + theArray->size, compare);
  	}
  	else return &undefined;
  
  	return Integer::intern(theArray->size);
  }
  

it sorts array by defined property...
an array of anything that has property
sortpv <array> <propname> [flip:false]

sample:

  (
  	delete objects
  	bb = #()
  	bb += for k=1 to 4 collect (box height:(random 1. 30.))
  	bb += for k=1 to 4 collect (cylinder height:(random 1. 30.))
  	bb += for k=1 to 4 collect (pyramid height:(random 1. 30.))
  		
  	t1 = timestamp()
  	m1 = heapfree
  	sortpv bb #height flip:on
  	format ">> t:% m:%\n" (timestamp() - t1) (m1 - heapfree)
  	for k=1 to bb.count do bb[k].pos.x += (k-1)*30
  )
  

another sample:

  try(form.close()) catch()
  (
  	global form = dotnetobject "Form"
  	form.ShowInTaskbar = off
  	form.AutoSize = on
  	form.AutoSizeMode = form.AutoSizeMode.GrowAndShrink
  	
  	bts = for k=0 to 10 collect
  	(
  		local bt = dotnetobject "button" 
  		bt.Bounds = dotnetobject "System.Drawing.Rectangle" 0 0 (random 10 100) 24
  		bt.tag = bt.Bounds.Width
  		bt
  	)
  	sortpv bts #tag
  	x = 0
  	for bt in bts do 
  	(
  		bt.Location.x = x
  		x += bt.Width
  	)
  	form.controls.addrange bts
  	
  	MaxHandleWrapper = dotnetobject "MaxCustomControls.Win32HandleWrapper" (dotnetobject "System.IntPtr" (windows.getmaxhwnd()))
  	form.Show MaxHandleWrapper
  	ok
  )
  


but... it's kinda slow. because common for all values _get_property method is very slow. i don't see any way to speed it up yet. any ideas?

but! it doesn't take any memory

Last edited by denisT : 01 January 2013 at 07:51 PM.
 
Old 01 January 2013   #3
why is it sortpv? "sort per value" or ""sort per property value"
 
Old 01 January 2013   #4
this one from my newer style "Function Publishing" library

#define range_check(_val, _lowerLimit, _upperLimit, _desc)					\
	if (_val < _lowerLimit || _val > _upperLimit) {							\
		TCHAR buf[256];														\
		TCHAR buf2[128];													\
		strcpy(buf,_desc);													\
		strcat(buf,_T(" < "));												\
		_snprintf(buf2, 128, _T("%g"), EPS(_lowerLimit));					\
		strcat(buf,buf2);													\
		strcat(buf,_T(" or > "));											\
		_snprintf(buf2, 128, _T("%g"), EPS(_upperLimit));					\
		strcat(buf,buf2);													\
		strcat(buf,_T(": "));												\
		_snprintf(buf2, 128, _T("%g"), EPS(_val));							\
		strcat(buf,buf2);													\
		throw RuntimeError (buf);											\
	}

MNMesh* getPolyMeshFromNode(INode* node, int accessType)
{
	MNMesh* poly = NULL;

	Object* obj = node->GetObjectRef();
	Object* base_obj = Get_Object_Or_XRef_BaseObject(obj);

	if(accessType == MESH_WRITE_ACCESS && obj != base_obj)
		throw RuntimeError(GetString(IDS_MODIFIER_PRESENT_ERR), obj->GetObjectName());
	else if(accessType == MESH_BASE_OBJ || accessType == MESH_WRITE_ACCESS)
	{
		if(base_obj->ClassID() != EPOLYOBJ_CLASS_ID)
			throw RuntimeError(GetString(IDS_OP_ON_NON_EPOLY), obj->GetObjectName());
		poly = &((PolyObject*)base_obj)->GetMesh();
	}
	else
	{
		ObjectState os = obj->Eval(MAXScript_time());
		obj = (Object*)os.obj;
		if(obj->ClassID() != EPOLYOBJ_CLASS_ID && obj->ClassID() != polyObjectClassID)
			throw RuntimeError(GetString(IDS_OP_ON_NON_EPOLY), obj->GetObjectName());
		poly = &((PolyObject*)obj)->GetMesh();
	}
	return poly;
}

void CFnLib::getMapVertsFromGeoVert(INode* node,  const int mapChannel, int vert, BitArray& mapverts)
{
// Get the mesh

   MNMesh* mesh = getPolyMeshFromNode(node, MESH_READ_ACCESS);
   if(mesh == NULL)
	  return;
	
// get the map

	MNMap* map = mesh->M(mapChannel);

// check for map support (something not workin' here!)

	if(map->GetFlag(MN_DEAD))
	{
		char buffer[33];
		throw RuntimeError("Map support not enabled for specified map channel: ", itoa(mapChannel,buffer,10));
	}

// check input bounds

	range_check(vert, 1, mesh->VNum(), "Map Vert Index Out of Range: ");	

// make sure input bitarray is the correct length

	mapverts.SetSize(map->VNum());
	mapverts.ClearAll();

// for all the faces
	
	int nFaces = mesh->FNum();
	for(int i=0; i < nFaces; i++)
	{
		MNFace*		geoface	= mesh->F(i);
		MNMapFace*	mapface	= map->F(i);

// skip over dead faces

		if(geoface->GetFlag(MN_DEAD)) 
			continue;

		int face_deg = geoface->deg;
		for(int j=0; j < face_deg; j++) 
		{
			if(geoface->vtx[j] == vert - 1)
			{
				mapverts.Set(mapface->tv[j]);
				break; // should only be one per face
			}
		}
	}
}


think it would be easily ported to the older Exposure Technique
 
Old 01 January 2013   #5
here's a few more lets you add "hidden" user data to a scene, uses the same owner class & super class id as the other mxs app data routines

 bool CFnLib::isSceneAppData(int id)
 {
 	return GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id) != 0;
 }
 
 // remove sceneapp data
 
 bool CFnLib::removeSceneAppData(int id)
 {
 	return GetCOREInterface()->GetScenePointer()->RemoveAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id) != 0;
 }
 
 void CFnLib::setSceneAppDataString(int id, const TCHAR* string)
 {
 	int len = strlen(string) + 1; // i'm guessing we'll need the terminator on return
 	char* cptr = (char *)MAX_malloc(len);
 	memcpy(cptr,string,len);
 
 // delete any old data
 
 	GetCOREInterface()->GetScenePointer()->RemoveAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
 
 // replace with new
 
 	GetCOREInterface()->GetScenePointer()->AddAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id, len, cptr);
 }
 
 
 TCHAR* CFnLib::getSceneAppDataString(int id)
 {
 	AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
 	if(appdata)
 		return ((TCHAR *)appdata->data);
 	return 0;
 }

Last edited by Klunk : 01 January 2013 at 03:23 PM.
 
Old 01 January 2013   #6
following this thread http://forums.cgsociety.org/showthr...?f=98&t=1031550

    #include "IPathConfigMgr.h"
 class PathConfigMgr : public FPInterfaceDesc
 {
 public:
 
 	static const Interface_ID id;
 	
 	enum FunctionIDs
 	{
 		_GetResolveUNC,
 		_SetResolveUNC,
 		_GetResolveToRelative,
 		_SetResolveToRelative,
 	};
 
 	PathConfigMgr() : FPInterfaceDesc(id, _M("PathConfigMgr"), 0, NULL, FP_CORE, end)
 	{
 		AppendFunction(
 			_GetResolveUNC, _M("GetResolveUNC"), 0, TYPE_BOOL, 0, 0, /* Number of arguments */
 			end); 
 		AppendFunction(
 			_SetResolveUNC, _M("SetResolveUNC"), 0, TYPE_BOOL, 0, 1, /* Number of arguments */
 				_M("flag"), 0, TYPE_BOOL,
 			end); 
 		AppendFunction(
 			_GetResolveToRelative, _M("GetResolveToRelative"), 0, TYPE_BOOL, 0, 0, /* Number of arguments */
 			end); 
 		AppendFunction(
 			_SetResolveToRelative, _M("SetResolveToRelative"), 0, TYPE_BOOL, 0, 1, /* Number of arguments */
 				_M("flag"), 0, TYPE_BOOL,
 			end); 
 	}
 
 	static bool GetResolveUNC() { 
 		return IPathConfigMgr::GetPathConfigMgr()->GetResolveUNC(); 
 	} 
 	static bool SetResolveUNC(BOOL flag) { 
 		bool prev = GetResolveUNC();
 		IPathConfigMgr::GetPathConfigMgr()->SetResolveUNC(flag == TRUE);
 		return prev; 
 	}
 	static bool GetResolveToRelative() { 
 		return IPathConfigMgr::GetPathConfigMgr()->GetResolveToRelative(); 
 	} 
 	static bool SetResolveToRelative(BOOL flag) {
 		bool prev = GetResolveToRelative();
 		IPathConfigMgr::GetPathConfigMgr()->SetResolveToRelative(flag == TRUE);
 		return prev; 
 	}
 
 	BEGIN_FUNCTION_MAP
 		FN_0(_GetResolveUNC, TYPE_BOOL, GetResolveUNC)
 		FN_1(_SetResolveUNC, TYPE_BOOL, SetResolveUNC, TYPE_BOOL)
 		FN_0(_GetResolveToRelative, TYPE_BOOL, GetResolveToRelative)
 		FN_1(_SetResolveToRelative, TYPE_BOOL, SetResolveToRelative, TYPE_BOOL)
 	END_FUNCTION_MAP
 
 };
 
 const Interface_ID PathConfigMgr::id = Interface_ID(0x62174bc6, 0x790c7394);
 static PathConfigMgr pathConfingExtInterface;
    

both set functions return previous state of the property.

max PathConfig interface doesn't provide these methods except GetResolveUNC.

Last edited by denisT : 01 January 2013 at 11:15 PM.
 
Old 01 January 2013   #7
it's different to how I do those and I'm a little confused with...

static PathConfigMgr GetResolveUNC;
static PathConfigMgr SetResolveUNC;
static PathConfigMgr GetResolveToRelative;
static PathConfigMgr SetResolveToRelative;


isn't that 4 instances of the same interface ? shouldn't something like...

static  PathConfigMgr  pcmgrInterface;


suffice ?
 
Old 01 January 2013   #8
you are right. it should be your way. it was a result of hasty copying.

Last edited by denisT : 01 January 2013 at 11:25 PM.
 
Old 01 January 2013   #9
i think you can loose the static on the member function definitions too, but other than than it's a really cool and compact way of doing it, and can be dropped straight into another interface project cpp file as is and you've got another interface with none of that tedious setting up visual studio project build settings or creating a new interface class and inheriting from that. I like it

copy and paste, build 30 secs later

 showinterface PathConfigMgr
   Interface: PathConfigMgr
    Properties:
    Methods:
 	<boolean>GetResolveUNC()
 	<boolean>SetResolveUNC flag
 	<boolean>GetResolveToRelative()
 	<boolean>SetResolveToRelative flag
    Actions:
 OK

Last edited by Klunk : 01 January 2013 at 08:42 AM.
 
Old 01 January 2013   #10
i liked it so much i switched my sceneappdata interface to a similar format.....

//**************************************************  ******************************************
  
  class SceneAppData : public FPInterfaceDesc
  {
  public:
  
  	static const Interface_ID id;
  
  	enum functions
  	{		
  		_isdata,
  		_remove,
  		_setint,
  		_getint,
  		_setflag,
  		_getflag,
  		_clearflag,
  		_setstring,
  		_getstring,
  		_setfloat,
  		_getfloat,
  		_setpoint3,
  		_getpoint3,
  		_setinttab,
  		_getinttab,
  		_setinttabvalue,
  		_getinttabvalue,
  		_setfloattab,
  		_getfloattab,
  		_setfloattabvalue,
  		_getfloattabvalue
  	};
  
  	SceneAppData() : FPInterfaceDesc(id, _M("sceneAppData"), 0, NULL, FP_CORE, end)
  	{
  		AppendFunction(	
  			_isdata, _M("isData"), 0, TYPE_BOOL, 0, 1,
  			_M("id"), 0, TYPE_INT, end);
  
  		AppendFunction(	
  			_remove, _M("remove"), 0, TYPE_BOOL, 0, 1,
  			_M("id"), 0, TYPE_INT, end);
  
  		
  		AppendFunction(	
  			_setint, _M("setInt"), 0, TYPE_BOOL, 0, 2,
  			_M("id"), 0, TYPE_INT,
  			_M("value"), 0, TYPE_INT, end);
  
  		AppendFunction(	
  			_getint, _M("getInt"), 0, TYPE_INT, 0, 1,
  			_M("id"), 0, TYPE_INT, end);
  
  		AppendFunction(	
  			_setflag, _M("setFlag"), 0, TYPE_BOOL, 0, 3,
  			_M("id"), 0, TYPE_INT,
  			_M("flag"), 0, TYPE_INT,
  			_M("setto"), 0, TYPE_INT, end);
  
  		AppendFunction(	
  			_getflag, _M("getFlag"), 0, TYPE_INT, 0, 2,
  			_M("id"), 0, TYPE_INT,
  			_M("flag"), 0, TYPE_INT, end);
  
  		AppendFunction(	
  			_clearflag, _M("clearFlag"), 0, TYPE_BOOL, 0, 2,
  			_M("id"), 0, TYPE_INT,
  			_M("flag"), 0, TYPE_INT,end);
  
  		AppendFunction(	
  			_setstring, _M("setString"), 0, TYPE_BOOL, 0, 2,
  			_M("id"), 0, TYPE_INT,
  			_M("string"), 0, TYPE_STRING, end);
  
  		AppendFunction(	
  			_getstring, _M("getString"), 0, TYPE_STRING, 0, 1,
  			_M("id"), 0, TYPE_INT, end);
  		AppendFunction(	
  			_setfloat, _M("setFloat"), 0, TYPE_BOOL, 0, 2,
  			_M("id"), 0, TYPE_INT,
  			_M("float"), 0, TYPE_FLOAT, end);
  
  		AppendFunction(	
  			_getfloat, _M("getFloat"), 0, TYPE_FLOAT, 0, 1,
  			_M("id"), 0, TYPE_INT, end);
  
  		AppendFunction(	
  			_setpoint3, _M("setPoint3"), 0, TYPE_BOOL, 0, 2,
  			_M("id"), 0, TYPE_INT,
  			_M("point3"), 0, TYPE_POINT3, end);
  
  		AppendFunction(	_getpoint3, _M("getPoint3"), 0, TYPE_POINT3, 0, 1,
  			_M("id"), 0, TYPE_INT, end);
  
  		AppendFunction(	
  			_setinttab, _M("setIntTab"), 0, TYPE_BOOL, 0, 2,
  			_M("id"), 0, TYPE_INT,
  			_M("int array"), 0, TYPE_INT_TAB_BR, end);
  
  		AppendFunction(	
  			_getinttab, _M("getIntTab"), 0, TYPE_INT, 0, 2,
  			_M("id"), 0, TYPE_INT,
  			_M("int array"), 0, TYPE_INT_TAB_BR, end);
  
  		AppendFunction(	
  			_setinttabvalue, _M("setIntTabValue"), 0, TYPE_BOOL, 0, 3,
  			_M("id"), 0, TYPE_INT,
  			_M("value"), 0, TYPE_INT,
  			_M("index"), 0, TYPE_INT, end);
  
  		AppendFunction(	
  			_getinttabvalue, _M("getIntTabValue"), 0, TYPE_INT, 0, 2,
  			_M("id"), 0, TYPE_INT,
  			_M("index"), 0, TYPE_INT,  end);
  
  		AppendFunction(	
  			_setfloattab, _M("setFloatTab"), 0, TYPE_BOOL, 0, 2,
  			_M("id"), 0, TYPE_INT,
  			_M("float array"), 0, TYPE_FLOAT_TAB_BR,  end);
  
  		AppendFunction(	
  			_getfloattab, _M("getFloatTab"), 0, TYPE_INT, 0, 2,
  			_M("id"), 0, TYPE_INT,
  			_M("float array"), 0, TYPE_FLOAT_TAB_BR,  end);
  
  		AppendFunction(	
  			_setfloattabvalue, _M("setFloatTabValue"), 0, TYPE_BOOL, 0, 3,
  			_M("id"), 0, TYPE_INT,
  			_M("value"), 0, TYPE_FLOAT,
  			_M("index"), 0, TYPE_INT,  end);
  
  		AppendFunction(	
  			_getfloattabvalue, _M("getFloatTabValue"), 0, TYPE_FLOAT, 0, 2,
  			_M("id"), 0, TYPE_INT,
  			_M("index"), 0, TYPE_INT,  end);
  	}
  
  //**************************************************  ******************************************
  
  // <bool> sceneAppData.isData   
  
  	bool isData(int id)
  	{
  		return GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id) != 0;
  	}
  
  // <bool> sceneAppData.remove  
  
  	bool remove(int id)
  	{
  		return GetCOREInterface()->GetScenePointer()->RemoveAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id) != 0;
  	}
  
  //**************************************************  ******************************************
  
  // <bool> sceneAppData.setInt   
  
  	bool setInt(int id, int value);
  
  // <int> sceneAppData.getInt   
  
  	int getInt(int id)
  	{
  		AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  		if(appdata)
  			return *((int *)appdata->data);
  		return 0;
  	}
  
  //**************************************************  ******************************************
  
  // <bool> sceneAppData.setFlag    
  
  	bool setFlag(int id, int f, int set)
  	{
  		AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id);  
  		if(appdata)
  		{
  			set ? *((int *)appdata->data) |= (1 << f) : *((int *)appdata->data) &= ~(1 << f);
  			return true;
  		}
  		else 
  			return setInt(id, (1 << f)); // create the appdata value as our flag.
  	}
  
  // <bool> sceneAppData.clearFlag    
  
  	bool clearFlag( int id, int f)
  	{
  		AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id);  
  		if(appdata)
  		{
  			*((int *)appdata->data) &= ~(1 << f);
  			return true;
  		}
  		else
  			return setInt(id, 0);
  	}
  
  // <bool> sceneAppData.getFlag    
  
  	int getFlag(int id, int f)
  	{
  		AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id);  
  		if(appdata)
  			return (int)((*((int *)appdata->data) & (1 << f)) != 0);
  		else
  			return 0;
  	}
  
  //**************************************************  ******************************************
  
  // <bool> sceneAppData.setString    
  
  	bool setString(int id, const TCHAR* string);
  
  // <string> sceneAppData.getString 
  
  	TCHAR* getString(int id)
  	{
  		AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  		if(appdata)
  			return ((TCHAR *)appdata->data);
  		return 0;
  	}
  
  //**************************************************  ******************************************
  
  // <bool> sceneAppData.setFloat    
  
  	bool setFloat(int id, float value);
  
  // <float> sceneAppData.getString 
  
  	float getFloat(int id)
  	{
  		AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  		if(appdata)
  			return *((float *)appdata->data);
  		return 0.0f;
  	}
  
  //**************************************************  ******************************************
  
  // <bool> sceneAppData.setPoint3    
  
  	bool setPoint3(int id, Point3& p);
  
  // <Point3> sceneAppData.getPoint3  
  
  	Point3* getPoint3(int id)
  	{
  		AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  		if(appdata)
  			return (Point3 *)appdata->data;
  		return NULL; // mxs sees this as undefined which is nice
  	}
  
  //**************************************************  ******************************************
  
  // <bool> sceneAppData.setIntTab  
  
  	bool setIntTab(int id, Tab<int>& intTab);
  
  // <int> sceneAppData.getIntTab  
  
  	int	getIntTab(int id, Tab<int>& intTab);
  
  // <bool> sceneAppData.setIntTabValue   
  
  	bool setIntTabValue(int id, int value, int index);
  
  // <int> sceneAppData.getIntTabValue   
  
  	int getIntTabValue(int id, int index);
  
  //**************************************************  ******************************************
  
  // <bool> sceneAppData.setFloatTab  
  
  	bool setFloatTab(int id, Tab<float>& floatTab);
  
  // <int> sceneAppData.getFloatTab  
  
  	int  getFloatTab(int id, Tab<float>& floatTab);
  
  // <bool> sceneAppData.setFloatTabValue   
  
  	bool setFloatTabValue(int id, float value, int index);
  
  // <float> sceneAppData.getFloatTabValue   
  
  	float getFloatTabValue(int id, int index);
  
  	BEGIN_FUNCTION_MAP
  		FN_1(_isdata, TYPE_BOOL, isData, TYPE_INT);
  		FN_1(_remove, TYPE_BOOL, remove, TYPE_INT);
  
  		FN_2(_setint, TYPE_BOOL, setInt, TYPE_INT, TYPE_INT);
  		FN_1(_getint, TYPE_INT, getInt, TYPE_INT);
  
  		FN_3(_setflag, TYPE_BOOL, setFlag, TYPE_INT, TYPE_INT, TYPE_INT);
  		FN_2(_getflag, TYPE_INT, getFlag,  TYPE_INT, TYPE_INT);
  		FN_2(_clearflag, TYPE_BOOL, clearFlag, TYPE_INT, TYPE_INT);
  
  		FN_2(_setstring, TYPE_BOOL, setString, TYPE_INT, TYPE_STRING);
  		FN_1(_getstring, TYPE_STRING, getString, TYPE_INT);
  
  		FN_2(_setfloat, TYPE_BOOL,setFloat, TYPE_INT, TYPE_FLOAT);
  		FN_1(_getfloat, TYPE_FLOAT, getFloat, TYPE_INT);
  
  		FN_2(_setpoint3, TYPE_BOOL, setPoint3,  TYPE_INT, TYPE_POINT3);
  		FN_1(_getpoint3, TYPE_POINT3, getPoint3, TYPE_INT);
  
  		FN_2(_setinttab, TYPE_BOOL, setIntTab, TYPE_INT, TYPE_INT_TAB_BR);
  		FN_2(_getinttab, TYPE_INT, getIntTab, TYPE_INT, TYPE_INT_TAB_BR);
  
  		FN_3(_setinttabvalue, TYPE_BOOL, setIntTabValue, TYPE_INT, TYPE_INT, TYPE_INT);
  		FN_2(_getinttabvalue, TYPE_INT, getIntTabValue, TYPE_INT, TYPE_INT);
  
  		FN_2(_setfloattab, TYPE_BOOL, setFloatTab, TYPE_INT, TYPE_FLOAT_TAB_BR);
  		FN_2(_getfloattab, TYPE_INT, getFloatTab, TYPE_INT, TYPE_FLOAT_TAB_BR);
  
  		FN_3(_setfloattabvalue, TYPE_BOOL,setFloatTabValue, TYPE_INT, TYPE_FLOAT, TYPE_INT);
  		FN_2(_getfloattabvalue, TYPE_FLOAT, getFloatTabValue, TYPE_INT, TYPE_INT);
  	END_FUNCTION_MAP
  };
  
  const Interface_ID SceneAppData::id = Interface_ID(0x9da3ed5, 0x6f30132b);
  static SceneAppData SceneAppDataInterface;
  
  //**************************************************  ******************************************
  
  bool SceneAppData::setInt(int id, int value)
  {
  	int* iptr = (int *)MAX_malloc(sizeof(int));
  	if(!iptr) return false;
  	*iptr = value;
  	GetCOREInterface()->GetScenePointer()->RemoveAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  	GetCOREInterface()->GetScenePointer()->AddAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id, sizeof(int), iptr);
  	return true;
  }
  
  //**************************************************  ******************************************
  
  bool SceneAppData::setString(int id, const TCHAR* string)
  {
  	int len = strlen(string) + 1; 
  	char* cptr = (char *)MAX_malloc(len);
  	if(!cptr) return false;
  	memcpy(cptr,string,len);
  	GetCOREInterface()->GetScenePointer()->RemoveAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  	GetCOREInterface()->GetScenePointer()->AddAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id, len, cptr);
  	return true;
  }
  
  //**************************************************  ******************************************
  
  bool SceneAppData::setFloat(int id, float value)
  {
  	float* fptr = (float *)MAX_malloc(sizeof(float));
  	if(!fptr) return false;
  	*fptr = value;
  	GetCOREInterface()->GetScenePointer()->RemoveAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  	GetCOREInterface()->GetScenePointer()->AddAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id, sizeof(float), fptr);
  	return true;
  }
  
  //**************************************************  ******************************************
  
  bool SceneAppData::setPoint3(int id, Point3& p)
  {
  	float* fptr = (float *)MAX_malloc(sizeof(Point3));
  	if(!fptr) return false;
  	memcpy(fptr,&p.x,sizeof(Point3));
  	GetCOREInterface()->GetScenePointer()->RemoveAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  	GetCOREInterface()->GetScenePointer()->AddAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id, sizeof(Point3), fptr);
  	return true;
  }
  
  //**************************************************  ******************************************
  
  bool SceneAppData::setIntTab(int id, Tab<int>& intTab)
  {
  	int numbytes = intTab.Count() * sizeof(int);
  	int* iptr = (int *)MAX_malloc(numbytes);
  	if(!iptr) return false;
  	memcpy(iptr,intTab.Addr(0),numbytes);
  	GetCOREInterface()->GetScenePointer()->RemoveAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  	GetCOREInterface()->GetScenePointer()->AddAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id, numbytes, iptr);
  	return true;
  }
  
  //**************************************************  ******************************************
  
  int SceneAppData::getIntTab(int id, Tab<int>& intTab)
  {
  	AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  	if(appdata)
  	{
  		int number_of_ints = appdata->length/sizeof(int);
  		intTab.SetCount(number_of_ints);
  		memcpy(intTab.Addr(0),appdata->data,appdata->length);
  		return number_of_ints;
  	}
  	return 0;
  }
  
  //**************************************************  ******************************************
  
  bool SceneAppData::setIntTabValue(int id, int value, int index)
  {
  	AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  	if(appdata)
  	{
  		int number_of_ints = appdata->length/sizeof(int);
  		range_check(index, 1, number_of_ints, "Int Array Index Out of Range: ");
  		((int *)appdata->data)[index - 1] = value;
  		return true;
  	}
  	return false;
  }
  
  //**************************************************  ******************************************
  
  int SceneAppData::getIntTabValue(int id, int index)
  {
  	AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  	if(appdata)
  	{
  		int number_of_ints = appdata->length/sizeof(int);
  		range_check(index, 1, number_of_ints, "Int Array Index Out of Range: ");	
  		return ((int *)appdata->data)[index - 1];
  	}
  	return 0;
  }
  
  //**************************************************  ******************************************
  
  bool SceneAppData::setFloatTab(int id, Tab<float>& floatTab)
  {
  	int numbytes = floatTab.Count() * sizeof(float);
  	float* fptr = (float *)MAX_malloc(numbytes);
  	if(!fptr) return false;
  	memcpy(fptr,floatTab.Addr(0),numbytes);
  	GetCOREInterface()->GetScenePointer()->RemoveAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  	GetCOREInterface()->GetScenePointer()->AddAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id, numbytes, fptr);
  	return true;
  }
  
  //**************************************************  ******************************************
  
  int SceneAppData::getFloatTab(int id, Tab<float>& floatTab)
  {
  	AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  	if(appdata)
  	{
  		int number_of_floats = appdata->length/sizeof(float);
  		floatTab.SetCount(number_of_floats);
  		memcpy(floatTab.Addr(0),appdata->data,appdata->length);
  		return number_of_floats;
  	}
  	return 0;
  }
  
  //**************************************************  ******************************************
  
  bool SceneAppData::setFloatTabValue(int id, float value, int index)
  {
  	AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  	if(appdata)
  	{
  		int number_of_floats = appdata->length/sizeof(float);
  		range_check(index, 1, number_of_floats, "Float Array Index Out of Range: ");	
  		((float *)appdata->data)[index - 1] = value; 
  		return true;
  	}
  	return false;
  }
  
  //**************************************************  ******************************************
  
  float SceneAppData::getFloatTabValue(int id, int index)
  {
  	AppDataChunk* appdata = GetCOREInterface()->GetScenePointer()->GetAppDataChunk(MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, id); 
  	if(appdata)
  	{
  		int number_of_floats = appdata->length/sizeof(float);
  		range_check(index, 1, number_of_floats, "Float Array Index Out of Range: ");	
  		return ((float *)appdata->data)[index - 1];	
  	}
  	return 0;
  }
  
  //**************************************************  ******************************************


the range_check macro can be found in \maxsdk\samples\maxscript\mxsagni\mxsagni.h. This interface can easily ported to hang the data off a node. Also the page encoding system seems to have stripped some of the comment description of the mxs call but it's pretty easy to work out.

Last edited by Klunk : 01 January 2013 at 11:13 AM.
 
Old 01 January 2013   #11
there are some another things not exposed to mxs:

class ISnap : public FPInterfaceDesc
{
public:

	static const Interface_ID id;

	enum FunctionIDs
	{
		_SnapAngle, 
		_SnapPercent,
		_GetSnapAngle,
		_SetSnapAngle,
		_GetSnapPercent,
		_SetSnapPercent,

		_ASnapStatus, 
		_SetASnapStatus, 
		_PSnapStatus, 
		_SetPSnapStatus, 
		_ToggleASnap, 
		_TogglePSnap, 
	};

	ISnap() : FPInterfaceDesc(id, _M("ISnap"), 0, NULL, FP_CORE, end)
	{
		AppendFunction(
			_SnapAngle,_M("SnapAngle"), 0, TYPE_FLOAT, 0, 3,
				_M("angle"), 0, TYPE_FLOAT,
				_M("fast"), 0 , TYPE_BOOL, f_keyArgDefault, TRUE,
				_M("force"), 0 , TYPE_BOOL, f_keyArgDefault, FALSE,
			end); 
		AppendFunction(
			_SnapPercent,_M("SnapPercent"), 0, TYPE_FLOAT, 0, 1,
				_M("percent"), 0, TYPE_FLOAT,
			end); 
		AppendFunction(
			_GetSnapAngle,_M("GetSnapAngle"), 0, TYPE_FLOAT, 0, 0,
			end); 
		AppendFunction(
			_SetSnapAngle,_M("SetSnapAngle"), 0, TYPE_VALUE, 0, 1,
				_M("val"), 0, TYPE_FLOAT,
			end); 
		AppendFunction(
			_GetSnapPercent,_M("GetSnapPercent"), 0, TYPE_FLOAT, 0, 0,
			end); 
		AppendFunction(
			_SetSnapPercent,_M("SetSnapPercent"), 0, TYPE_VALUE, 0, 1,
				_M("val"), 0, TYPE_FLOAT,
			end); 

		AppendFunction(
			_ASnapStatus,_M("GetAngleSnapStatus"), 0, TYPE_bool, 0, 0,
			end); 
		AppendFunction(
			_SetASnapStatus,_M("SetAngleSnapStatus"), 0, TYPE_bool, 0, 1,
				_M("val"), 0, TYPE_bool,
			end); 
		AppendFunction(
			_PSnapStatus,_M("GetPercentSnapStatus"), 0, TYPE_bool, 0, 0,
			end); 
		AppendFunction(
			_SetPSnapStatus,_M("SetPercentSnapStatus"), 0, TYPE_bool, 0, 1,
				_M("val"), 0, TYPE_bool,
			end); 
		AppendFunction(
			_ToggleASnap,_M("ToggleAngleSnap"), 0, TYPE_bool, 0, 0,
			end); 
		AppendFunction(
			_TogglePSnap,_M("TogglePercentSnap"), 0, TYPE_bool, 0, 0,
			end); 
	}

	static float SnapAngle(float angle, BOOL fast = TRUE, BOOL force = FALSE) {
		return GetCOREInterface()->SnapAngle(angle, fast, force);
	}
	static float SnapPercent(float percent) {
		return GetCOREInterface()->SnapPercent(percent);
	}
	static float GetSnapAngle() {
		return MAXScript_interface7->GetSnapAngle();
	}
	static Value* SetSnapAngle(float val) {
		MAXScript_interface7->SetSnapAngle(val);
		return &ok;
	}
	static float GetSnapPercent() {
		return MAXScript_interface7->GetSnapPercent();
	}
	static Value* SetSnapPercent(float val) {
		MAXScript_interface7->SetSnapPercent(val);
		return &ok;
	}
	static int GetAngleSnapStatus() {
		return MAXScript_interface7->ASnapStatus();
	}
	static bool SetAngleSnapStatus(bool val) {
		bool prev = (MAXScript_interface7->ASnapStatus()) ? true : false;
		if (prev != val) MAXScript_interface7->ToggleASnap();
		return val;
	}
	static int GetPercentSnapStatus() {
		return MAXScript_interface7->PSnapStatus();
	}
	static bool SetPercentSnapStatus(bool val) {
		bool prev = (MAXScript_interface7->PSnapStatus()) ? true : false;
		if (prev != val) MAXScript_interface7->TogglePSnap();
		return val;
	}
	static bool ToggleAngleSnap() {
		MAXScript_interface7->ToggleASnap();
		return MAXScript_interface7->ASnapStatus() != 0;
	}
	static bool TogglePercentSnap() {
		MAXScript_interface7->TogglePSnap();
		return MAXScript_interface7->PSnapStatus() != 0;
	}
	BEGIN_FUNCTION_MAP
		FN_3(_SnapAngle, TYPE_FLOAT, SnapAngle, TYPE_FLOAT, TYPE_BOOL, TYPE_BOOL)
		FN_1(_SnapPercent, TYPE_FLOAT, SnapPercent, TYPE_FLOAT)
		FN_0(_GetSnapAngle, TYPE_FLOAT, GetSnapAngle)
		FN_1(_SetSnapAngle, TYPE_VALUE, SetSnapAngle, TYPE_FLOAT)
		FN_0(_GetSnapPercent, TYPE_FLOAT, GetSnapPercent)
		FN_1(_SetSnapPercent, TYPE_VALUE, SetSnapPercent, TYPE_FLOAT)
		FN_0(_ASnapStatus, TYPE_bool, GetAngleSnapStatus)
		FN_1(_SetASnapStatus, TYPE_bool, SetAngleSnapStatus, TYPE_bool)
		FN_0(_PSnapStatus, TYPE_bool, GetPercentSnapStatus)
		FN_1(_SetPSnapStatus, TYPE_bool, SetPercentSnapStatus, TYPE_bool)
		FN_0(_ToggleASnap, TYPE_bool, ToggleAngleSnap)
		FN_0(_TogglePSnap, TYPE_bool, TogglePercentSnap)
	END_FUNCTION_MAP

};
const Interface_ID ISnap::id = Interface_ID(0x02feb1967, 0x790a7898);
static ISnap isnapInterface;
 
Old 01 January 2013   #12
i can't find any sample how to append property to FPInterfaceDesc.
there is the AppendProperty method but how to define the property SET and GET methods? thanks in advance...
 
Old 01 January 2013   #13
hey denis I'm not sure you really need those member functions to be declared as static. static member functions are used (for the most part) if you need to call a function on a class that hasn't been instanced e.g. for getting and setting static class members before the class is initiated. You could try removing

static ISnap isnapInterface;


and see if it still works I suppose.

theres examples of the property and enumeration setting in maxsdk\help\3dsMaxSDK.chm under function publishing :: property Accessors and
function publishing :: symbolic Enumerations


if you didn't know another technique you can use in function publishing is to pass return values as a pointer even single int sized values because if you return NULL max will auto convert it to undefined in mxs

Last edited by Klunk : 01 January 2013 at 06:23 PM.
 
Old 01 January 2013   #14
Originally Posted by claude666: theres examples of the property and enumeration setting in maxsdk\help\3dsMaxSDK.chm under function publishing :: property Accessors and
function publishing :: symbolic Enumerations

thanks... but i'm still not clear about the syntax.
 
Old 01 January 2013   #15
your PathConfigMgr example with a property called radius

class PathConfigMgr : public FPInterfaceDesc
    {
    public:
    
    	static const Interface_ID id;
    	
    	enum FunctionIDs
    	{
    		_getresolveunc,_setresolveunc,_getresolvetorelativ  e,_setresolvetorelative, _getRadius, _setRadius
    	};
    
    	PathConfigMgr() : FPInterfaceDesc(id, _M("PathConfigMgr"), 0, NULL, FP_CORE, end)
    	{
    		AppendFunction(
    			_getresolveunc, _M("GetResolveUNC"), 0, TYPE_BOOL, 0, 0,
    			end); 
    
    		AppendFunction(
    			_setresolveunc, _M("SetResolveUNC"), 0, TYPE_BOOL, 0, 1, 
    				_M("flag"), 0, TYPE_BOOL,
    			end); 
    
    		AppendFunction(
    			_getresolvetorelative, _M("GetResolveToRelative"), 0, TYPE_BOOL, 0, 0, 
    			end);
    
    		AppendFunction(
    			_setresolvetorelative, _M("SetResolveToRelative"), 0, TYPE_BOOL, 0, 1, 
    				_M("flag"), 0, TYPE_BOOL,
    			end); 
    
    		AppendProperty(_getRadius, _setRadius, _T("radius"), IDS_RADIUS,
    		   TYPE_FLOAT, f_range, 0.0, 10000.0, end); 
    
    	}
    	float r;
    	float GetRadius() { return r; }
    	void SetRadius(float radius) { r = radius; }
    
    	bool GetResolveUNC() 
    	{ 
    		return IPathConfigMgr::GetPathConfigMgr()->GetResolveUNC(); 
    	} 
    	bool SetResolveUNC(BOOL flag) 
    	{ 
    		bool prev = GetResolveUNC();
    		IPathConfigMgr::GetPathConfigMgr()->SetResolveUNC(flag == TRUE);
    		return prev; 
    	}
    	bool GetResolveToRelative() 
    	{ 
    		return IPathConfigMgr::GetPathConfigMgr()->GetResolveToRelative(); 
    	} 
    	bool SetResolveToRelative(BOOL flag)
    	{
    		bool prev = GetResolveToRelative();
    		IPathConfigMgr::GetPathConfigMgr()->SetResolveToRelative(flag == TRUE);
    		return prev; 
    	}
    
    	BEGIN_FUNCTION_MAP
    		FN_0(_getresolveunc, TYPE_BOOL, GetResolveUNC)
    		FN_1(_setresolveunc, TYPE_BOOL, SetResolveUNC, TYPE_BOOL)
    		FN_0(_getresolvetorelative, TYPE_BOOL, GetResolveToRelative)
    		FN_1(_setresolvetorelative, TYPE_BOOL, SetResolveToRelative, TYPE_BOOL)
    
    		PROP_FNS(_getRadius, GetRadius, _setRadius, SetRadius, TYPE_FLOAT);
    
    	END_FUNCTION_MAP
    
    };
    
    const Interface_ID PathConfigMgr::id = Interface_ID(0x62174bc6, 0x790c7394);
    static PathConfigMgr PathConfigMgrInterface;


showinterface PathConfigMgr
     Interface: PathConfigMgr
      Properties:
   	.radius : float : Read|Write|Validated by Range: 0.0 to 10000.0
      Methods:
   	<boolean>GetResolveUNC()
   	<boolean>SetResolveUNC flag
   	<boolean>GetResolveToRelative()
   	<boolean>SetResolveToRelative flag
      Actions:
   OK


also if you add something like

 r(100.0f)


to the constructor initializer list then radius will 100.0f at startup

Quote: thanks... but i'm still not clear about the syntax.


good now you know how we feel looking at some of your mxs stuff

Last edited by Klunk : 01 January 2013 at 06:54 PM.
 
reply share thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 08:12 PM.


Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.