[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
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