[Closed] A couple of controller plugin questions
So I’ve been following along with the “learning path” of the SDK documentation, and I’ve hit a bit of a snag on lesson 4. I am able to get it to compile and run, and it works as intended in Max, but if I try to save I am given the message
File Save Error
Unknown class: SuperID =0x900B, ClassID =(0x0,0x0)
In my ClassDesc extension, I have:
SClass_ID SuperClassID() { return CTRL_POSITION_CLASS_ID; }
Class_ID ClassID() { return Class_ID(0x2373c023, 0x4e2fe60a); }// randomly generated class ID
0x900B is the position controller superclass definition for CTRL_POSITION_CLASS_ID, so that’s working fine, but the class ID seems to be returning the wrong value.
On a related note, when I try to examine the controller in the maxscript listener, $.position.controller returns Controller:ReferenceTarget. I’m not sure where that name actually comes from as it is not specified anywhere in my code, and when I check its class, it returns DummyClass.
Can anyone tell me what I’m doing wrong?
is it somehow conflicting with the original position controller plugin that shipped with 3ds Max?
I don’t think so. Like I said, it’s working as a controller, just not being identified properly when either checked from MSX or trying to save the file.
Look at your Controller’s Save method then and see if there’s a conflict… compile a hybrid plugin version and then start 3ds Max thru the Visual Studio “Start Debug” session. Then you’ll likely see where it’s crashing.
There are no save methods in the lesson files. The wizard added
IOResult Save(ISave *isave) {return IO_OK;}
by default, but that obviously doesn’t actually do anything. I’m guessing that save support for controllers simply isn’t covered by the lesson and that I’ll have to look elsewhere for that information.
But that still doesn’t explain why I’m getting (0x0,0x0) as my class ID. Also, when I try to use Start Debugging, I get an error “Unable to start program ‘C:\etc\etc.dlc’.” I’ve been able to use this for the previous lessons, so I’m not sure why it’s a problem now.
This is from the position constraint’s code (from an older SDK):
#define OFFSET_POS_LOCAL_CHUNK 0x1001
#define OFFSET_POS_WORLD_CHUNK 0x1002
#define INITIAL_POSITION_CHUNK 0x1003
#define OLD_TARGET_NUMBER_CHUNK 0x1004
IOResult PosConstPosition::Save(ISave *isave)
{
ULONG nb;
// Save basePointLocal
isave->BeginChunk(OFFSET_POS_LOCAL_CHUNK);
isave->Write(&basePointLocal, sizeof(basePointLocal), &nb);
isave->EndChunk();
// Save basePointWorld
isave->BeginChunk(OFFSET_POS_WORLD_CHUNK);
isave->Write(&basePointWorld, sizeof(basePointWorld), &nb);
isave->EndChunk();
// Save InitialPosition
isave->BeginChunk(INITIAL_POSITION_CHUNK);
isave->Write(&InitialPosition,sizeof(InitialPosition),&nb);
isave->EndChunk();
// Save oldTargetNumber
isave->BeginChunk(OLD_TARGET_NUMBER_CHUNK);
isave->Write(&oldTargetNumber,sizeof(oldTargetNumber),&nb);
isave->EndChunk();
return IO_OK;
}
without the whole code to look at (not having had that exact issue) its tough to diagnose.
without the whole code to look at (not having had that exact issue) its tough to diagnose.
ControllerPlugin.cpp:
#include "ControllerPlugin.h"
#include "math.h"
#define ControllerPlugin_CLASS_ID Class_ID(0x6078d79e, 0x847f414a)
class ControllerPlugin : public Control {
public:
ControllerPlugin() { }
~ControllerPlugin() { }
SClass_ID SuperClassID() { return CTRL_POSITION_CLASS_ID; }
int NumRefs() {return 0; }
ReferenceTarget *GetReference (int i) {return NULL;}
void SetReference (int i, ReferenceTarget* pTarget) { }
RefResult NotifyRefChanged (Interval, RefTargetHandle, PartID&, RefMessage) {return REF_DONTCARE;}
void Copy (Control *pFrom) { }
void GetValue (TimeValue t, void *ptr, Interval &valid, GetSetMethod method);
void SetValue (TimeValue t, void *ptr, int commit, GetSetMethod method);
};
void ControllerPlugin::GetValue(TimeValue t, void *ptr, Interval &valid, GetSetMethod method) {
Point3 p3OurAbsValue(0, 0, 0);
p3OurAbsValue.x = 15 * sin( (float)t / 960 );
p3OurAbsValue.y = (float)t / 192;
valid.Set(t, t+1);
if (method == CTRL_ABSOLUTE) {
Point3* p3InVal = (Point3 *)ptr;
*p3InVal = p3OurAbsValue;
}
else {
Matrix3 *m3InVal = (Matrix3 *)ptr;
m3InVal->PreTranslate(p3OurAbsValue);
}
}
void ControllerPlugin::SetValue(TimeValue t, void *ptr, int commit, GetSetMethod method) { }
class ControllerPluginClassDesc : public ClassDesc {
public:
ControllerPluginClassDesc() { }
~ControllerPluginClassDesc() { }
BOOL HasClassParams() { return TRUE; }
int IsPublic() { return TRUE; }
void *Create(BOOL loading) { return new ControllerPlugin; }
const TCHAR *ClassName() { return GetString(IDS_CLASS_NAME); }
SClass_ID SuperClassID() { return CTRL_POSITION_CLASS_ID; }
Class_ID ClassID() { return Class_ID(0x2373c023, 0x4e2fe60a); }
const TCHAR *Category() { return _T(""); }
const TCHAR *InternalName() { return _T("ControllerPlugin"); }
HINSTANCE HInstance() { return hInstance; }
};
ClassDesc *GetControllerPluginDesc() {
static ControllerPluginClassDesc ControllerPluginDesc;
return &ControllerPluginDesc;
}
DllEntry.cpp
#include "ControllerPlugin.h"
extern ClassDesc2 *GetControllerPluginDesc();
HINSTANCE hInstance;
int controlsInit = FALSE;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, ULONG fdwReason, LPVOID) {
if(fdwReason == DLL_PROCESS_ATTACH) {
hInstance = hinstDLL;
DisableThreadLibraryCalls(hInstance);
}
return(TRUE);
}
__declspec(dllexport) int LibNumberClasses() { return 1; }
__declspec(dllexport) ULONG LibVersion() { return VERSION_3DSMAX; }
__declspec(dllexport) const TCHAR* LibDescription() { return GetString(IDS_LIBDESCRIPTION); }
__declspec(dllexport) ClassDesc2 *LibClassDesc(int i) {
switch(i) {
case 0: return GetControllerPluginDesc();
default: return 0;
}
}
__declspec(dllexport) int LibInitialize (void) { return TRUE; }
__declspec(dllexport) int LibShutdown (void) { return TRUE; }
TCHAR *GetString(int id) {
static TCHAR buf[256];
if (hInstance) return LoadString(hInstance, id, buf, sizeof(buf)) ? buf : NULL;
return NULL;
}
ControllerPlugin.h:
#include "3dsmaxsdk_preinclude.h"
#include "Max.h"
#include "resource.h"
#include "istdplug.h"
#include "iparamb2.h"
#include "iparamm2.h"
//SIMPLE TYPE
extern TCHAR *GetString(int id);
extern HINSTANCE hInstance;
theres a whole host of missing methods, which mean max will call the base class version
try implementing these 2
Class_ID ClassID();
void GetClassName(TSTR& str);
in the control class for starters… hate that bloody wizard, worst thing ever for SDK development must have scared of hundreds off ! if not working correctly or crashing.
As someone who is stumbling through the process of learning the SDK, I would say the wizard is a good idea, but badly implemented. Without any starting point at ALL, I would probably be even more lost than I already am, especially since the documentation for the setup process is so bad.
Getting very frustrated here…
First things first, I keep getting that “No Debugging Information, Debugging information for ‘3dsmax.exe’ cannot be found or does not match. Cannot find or open the PDB file. Do you want to continue debugging?” error.
At one point I had 2 versions of the same file, and it was working for one but not the other. The difference when I examined the actual file structure was that the working one had a .x64 folder containing a file called “ControllerPlugin.dlc.pdb”. To check if this was what was actually making it work, I temporarily renamed that folder, and sure enough that broke it. But then when I tried to put it back the way it was, it still didn’t work.
I have fairly limited experience working with Visual Studio/C++, so perhaps this is a simple issue that I am missing. I’ve tried looking up how to fix this problem, but of the solutions I found, they either did not work or I could not understand them.
Do this in Visual Studio:
In the Build Menu select: Clean Solution
It may not delete the .pdb file– so go ahead and delete that file/folder where it is… it will be recreated when you compile your plugin again.
For debugging, unless you have the full debug version of 3ds Max, you’ll need to build a Hybrid plugin. After you place the hybrid plugin in your \plugins folder and you start a Debug session in Visual Studio… you can dismiss that warning it first gives you about missing debug info… it’ll then finish launching 3ds Max and your debug session is active…