Notifications
Clear all

[Closed] [SDK and MaxScript] Control a plugin via Maxscript

Hey,

already the next question from me.

We would like to connect a Maxscript UI (macroscript with a rollout) to a SDK-function.

So imagine a performancecritique function that is written in C++ in the SDK. Is it now possible to start this function with custom parameters with a Macroscript? This would be a lot easier then the parameterblocks/maps.

Or is it in gerenal possible to add Maxscript-Support for a plugin?

Thanks for your ideas.

Florian

10 Replies

function publishing very simple to add mxs control to a plugin…

this is the function publishing to one our quad lighting tools

//*****************************************************************************************
 // function publishing, make some basic functionality available to mxs mostly so we can call our
 // utility from the ui via a macroscript without switching to the utility panel first !
 
 class QuadLightingFnP : public FPStaticInterface 
 {
 public:
 	DECLARE_DESCRIPTOR(QuadLightingFnP);
 
 	enum functionID { kOpenDialog, kCloseDialog, kIsChecked };
 	
 	BEGIN_FUNCTION_MAP			
 		VFN_0(kOpenDialog,  OpenDialog)
 		VFN_0(kCloseDialog, CloseDialog)
 		FN_0(kIsChecked, TYPE_BOOL, IsDialogChecked)
 	END_FUNCTION_MAP
 	
 	void OpenDialog() { quadUtil.CreateNewWindow(); }
 	void CloseDialog() { if(quadUtil.floaterHWND != NULL)  DestroyWindow(quadUtil.floaterHWND); }
 	bool IsDialogChecked() { return IsDialogShowing(); }
 
 	static bool IsDialogShowing() { return dialogShowing; }
 	static void SetDialogShowing(bool val) { dialogShowing = val; GetCUIFrameMgr()->SetMacroButtonStates(false); }
 
 private:
 	static bool dialogShowing;
 };
 
 //**************************************************************************************
 // create the global static instance
 
 static QuadLightingFnP theQuadLightingFnP(QUAD_LIGHTING_UTIL_FP_INTERFACE_ID, _T("QuadLighting"), -1, 0, FP_CORE,
 							QuadLightingFnP::kOpenDialog,	_T("openDialog"), -1, TYPE_VOID, FP_NO_REDRAW, 0,
 							QuadLightingFnP::kCloseDialog,	_T("closeDialog"), -1, TYPE_VOID, FP_NO_REDRAW, 0,
 							QuadLightingFnP::kIsChecked,	_T("isChecked"), -1, TYPE_BOOL, FP_NO_REDRAW, 0,end);
 
 //*****************************************************************************************
 // initialize the showing static
 
 bool QuadLightingFnP::dialogShowing = false;

then from mxs

QuadLighting.openDialog()

etc

Ah, thanks. That was exactly what I was looking for. Easy to understand and works great. :drool:
If somebody has the same problem. Here’s some more information:

http://area.autodesk.com/blogs/chris/adding_new_functions_written_in_c_to_maxscript

EDIT: And for newer SDKs use ParamTags::p_end instead of end.

Hi, I was wondering how you created the window by code ? As I’ve got the FP to work, but have no idea how to get the window to open up Thanks

theres a full example with all the function publishing etc \maxsdk\samples\utilities\ChannelInfo\TreeViewUtil.vcproj

Thats great, it now opens up the Dialog. Although it only works if it has created the instance first (Clicking on the hammer tool and selecting). So how would you open the Dialog if the instance isn’t created yet? As I would like to open up the dialog by Hotkey instead of keep having to create the instance every time I open Max before I can use the Hotkey. Thanks

isn’t that what the function publishing is for ? so you can bind your utility to maxscript so it can be called via a macroscript.

I agree, but at the moment, I have to open it via the hammer before I use the hotkey. Once it has been opened once, the code works fine, but unless I do it that it, it crashes max.

Hi, I was able to fix the issue I had with FP, although a new one has appeared. I am creating a Utility, but none of the Utilities will work unless its goes through the virtual void BeginEditParams, which I can’t call with FP. Anyway to get around this ? Thanks

heres a paired down verions of what I use (though i think most utilities can be better implemented as modifiers)

#include "Max.h"
  #include "istdplug.h"
  #include "iparamb2.h"
  #include "iparamm2.h"
  #include "notify.h"
  #include "modstack.h"
  #include "macrorec.h"
  #include "utilapi.h"
  #include "iFnPub.h"
  #include "..\resource\resource.h"
  
  extern TCHAR *GetString(int id);
  extern HINSTANCE hInstance;
  
  #define DEMO_WINDOW_UTIL_CLASS_ID			Class_ID(0xe823fa8, 0x21c0384c)
  #define DEMO_WINDOW_UTIL_FP_INTERFACE_ID	Interface_ID(0x436202d5, 0x70000ea6)
  
  //********************************************************************************************
  // DemoWindowUtil Our Tools class definition
  
  class DemoWindowUtil : public UtilityObj 
  {
  public:
  
  	HWND			hPanel;			// utility rollout panel
  	IUtil			*iu;
  	Interface		*ip;
  	HWND			floaterHWND;	// our floating window
  	
  // Constructor/Destructor
  
  	DemoWindowUtil();
  	~DemoWindowUtil() {}
  
  // stuff for the utility panel
  
  	void BeginEditParams(Interface *ip,IUtil *iu);
  	void EndEditParams(Interface *ip,IUtil *iu);
  
  // util panel
  
  	void Init(HWND hWnd)	{}
  	void Destroy(HWND hWnd) {}
  	void DeleteThis()		{}		
  
  // tool window handling routines
  
  	void CreateNewWindow();	
  	void InitWindow();
  	void DestroyWindow();
  	void UpdateUI();
  	LRESULT NotifyHandler( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  
  };
  
  // our util global static
  
  static DemoWindowUtil demoUtil;
  
  //********************************************************************************************
  // the class descriptor
  
  class DemoWindowUtilClassDesc : public ClassDesc2 
  {
  public:
  	int 			IsPublic()					{ return TRUE; }
  	void *			Create(BOOL loading=FALSE)	{ return &demoUtil; }
  	const TCHAR *	ClassName()					{ return GetString(IDS_DEMO_CLASS_NAME); }
  	SClass_ID		SuperClassID()				{ return UTILITY_CLASS_ID; }
  	Class_ID		ClassID()					{ return DEMO_WINDOW_UTIL_CLASS_ID; }
  	const TCHAR* 	Category()					{ return GetString(IDS_CATEGORY); }
  	const TCHAR*	InternalName()				{ return _T("DemoWindowUtil"); }	
  	HINSTANCE		HInstance()					{ return hInstance; }	// returns owning module handle
  };
  
  static DemoWindowUtilClassDesc DemoWindowUtilDesc;
  ClassDesc2* GetDemoWindowUtilDesc() { return &DemoWindowUtilDesc; }
  
  //*****************************************************************************************
  // function publishing, make some basic functionality available to mxs mostly so we can call our
  // utility from the ui via a macroscript without switching to the utility panel first !
  
  class DemoWindowFnP : public FPStaticInterface 
  {
  public:
  	DECLARE_DESCRIPTOR(DemoWindowFnP);
  
  	enum functionID { kOpenDialog, kCloseDialog, kIsChecked };
  	
  	BEGIN_FUNCTION_MAP			
  		VFN_0(kOpenDialog,  OpenDialog)
  		VFN_0(kCloseDialog, CloseDialog)
  		FN_0(kIsChecked, TYPE_BOOL, IsDialogChecked)
  	END_FUNCTION_MAP
  	
  	void OpenDialog() { demoUtil.CreateNewWindow(); }
  	void CloseDialog() { if(demoUtil.floaterHWND != NULL)  DestroyWindow(demoUtil.floaterHWND); }
  	bool IsDialogChecked() { return IsDialogShowing(); }
  
  	static bool IsDialogShowing() { return dialogShowing; }
  	static void SetDialogShowing(bool val) { dialogShowing = val; GetCUIFrameMgr()->SetMacroButtonStates(false); }
  
  private:
  
  	static bool dialogShowing;
  };
  
  //**************************************************************************************
  // create the global static instance
  
  static DemoWindowFnP theDemoWindowFnP(DEMO_WINDOW_UTIL_FP_INTERFACE_ID, _T("demoUtil"), IDS_DEMO_CLASS_NAME, 
  									  NULL, FP_CORE,
  							DemoWindowFnP::kOpenDialog,	_T("openDialog"), -1, TYPE_VOID, FP_NO_REDRAW, 0,
  							DemoWindowFnP::kCloseDialog, _T("closeDialog"), -1, TYPE_VOID, FP_NO_REDRAW, 0,
  							DemoWindowFnP::kIsChecked, _T("isChecked"), -1, TYPE_BOOL, FP_NO_REDRAW, 0,end);
  
  //**************************************************************************************
  // initialize the showing static
  
  bool DemoWindowFnP::dialogShowing = false;
  
  
  static INT_PTR CALLBACK DemoWindowUtilPanelProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  {
  	switch (msg) 
  	{
  		case WM_INITDIALOG:
  
  			demoUtil.Init(hWnd); // can we delete these ?
  			break;
  
  		case WM_DESTROY:
  
  			demoUtil.Destroy(hWnd); // can we delete these ?
  			break;
  
  		case WM_COMMAND:
  
  			switch (LOWORD(wParam)) 
  			{
  				case IDC_NEW_FLOATER_BTN:
  
  					demoUtil.CreateNewWindow();
  					break;
  
  				case IDOK:
  				case IDCANCEL:
  
  					DestroyWindow(hWnd);
  					break;
  			}
  			break;
  
  		case WM_LBUTTONDOWN:
  		case WM_LBUTTONUP:
  		case WM_MOUSEMOVE:
  
  			demoUtil.ip->RollupMouseMessage(hWnd,msg,wParam,lParam); 
  			break;
  
  		default:
  			return FALSE;
  	}
  	return TRUE;
  }
  
  //**************************************************************************************
  // the main handler callback for our floating tool window
  
  static INT_PTR CALLBACK DemoWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  {
  	switch (msg) 
  	{
  		case WM_INITDIALOG: 
  		{
  			demoUtil.floaterHWND = hWnd;
  			demoUtil.InitWindow();
  			demoUtil.ip->RegisterDlgWnd(hWnd);
  			demoUtil.UpdateUI();
  			DemoWindowFnP::SetDialogShowing(true);
  			break;
  		}
  
  		case WM_DESTROY: 
  		{
  			demoUtil.DestroyWindow();
  			demoUtil.ip->UnRegisterDlgWnd(hWnd);
  			DemoWindowFnP::SetDialogShowing(false);
  			break;
  		}
  
  		case WM_RBUTTONDOWN:
  		{
  			break;
  		}
  		
  		case WM_NOTIFY:
  
  			return demoUtil.NotifyHandler(hWnd, msg, wParam, lParam);
  			break;
  
  
  // handle custom max controls handled here spinners etc here e.g.
  
  //		case CC_SPINNER_CHANGE: 
  //		case CC_COLOR_SEL:
  //		case CC_COLOR_CHANGE:
  //		case CC_COLOR_CLOSE:
  
  		case WM_COMMAND:
  
  			switch (LOWORD(wParam)) 
  			{
  // all other win32 dialog handled here		
  
  				case IDOK:
  				case IDCANCEL:
  
  					DestroyWindow(hWnd);
  					break;
  			}
  			break;
  
  		default:
  			return FALSE;
  	}
  	return TRUE;
  }
  
  //**************************************************************************************
  // DemoWindowUtil, code for our utility starts here
  
  DemoWindowUtil::DemoWindowUtil()
  {
  	iu = NULL;
  	ip = NULL;	
  	hPanel = NULL;
  	floaterHWND = NULL;
  }
  
  //*****************************************************************************************
  
  void DemoWindowUtil::BeginEditParams(Interface *ip,IUtil *iu) 
  {
  	this->iu = iu;
  	this->ip = ip;
  	hPanel = ip->AddRollupPage(hInstance, MAKEINTRESOURCE(IDD_DEMO_WINDOW_PANEL), 
  		DemoWindowUtilPanelProc, GetString(IDS_PARAMS), 0);
  }
  	
  //********************************************************************************************
  
  void DemoWindowUtil::EndEditParams(Interface *ip,IUtil *iu) 
  {
  	this->iu = NULL;
  	ip->DeleteRollupPage(hPanel);
  	hPanel = NULL;
  }
  
  //*****************************************************************************************
  
  void DemoWindowUtil::CreateNewWindow()
  {
  	ip = GetCOREInterface();	// catches any script calls
  	if(floaterHWND == NULL)
  		CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DEMO_WINDOW), ip->GetMAXHWnd(), DemoWindowProc);
  }
  
  //**************************************************************************************
  
  LRESULT DemoWindowUtil::NotifyHandler( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  {
  	return 0L;
  }
  
  //**************************************************************************************
  // Initialize the tool window
  
  void DemoWindowUtil::InitWindow()  
  {
  }
  
  //**************************************************************************************
  // destroy the tool window
  
  void DemoWindowUtil::DestroyWindow()
  {
  	floaterHWND = NULL;
  }
  
  //*****************************************************************************************
  
  void DemoWindowUtil::UpdateUI() {}

IDD_DEMO_WINDOW_PANEL is the utility panel resourse (usually just a single button IDC_NEW_FLOATER_BTN in our case.
and IDD_DEMO_WINDOW is the actual floating window resource

Page 1 / 2