TBasicPart and fully customized UI elements ?

I'm looking into the feasibility of a new plugin but it's going to need its own fully customized user interface to be viable.  I'd need to be able to freely redraw in areas of the UI and track mouse clicks and movements.  Standard sliders or custom image parts etc won't cut it and don't give any live tracking through ::HandleEvent(). TBasicPart has ::SelfDraw() and lots of ::SelfMouse functions.  The step by step module/modeler example in the SDK uses TBasicPart with its module window and gives some guidance as to how to implement it.  Otherwise that sample code appears to be broken after Carrara 4.

So can TBasicPart be used with a 'node' part in any other type of plugin UI ?  Can I use it to add my own widgets into the UI ?

I tried to test this with the following approach based on the Modeler example, which uses TBasicModule: Inside MCSketch I added a Node resource then put some static text into the parent TMFNodePart so I could see it.  I left the TMFNodePart Part ID: empty.  In the resource (.r) file I added in a COMP and GUID resource with the same resource ID that I used in MCSketch.

resource 'COMP' (130)
    'part',            // kMFPartResourceType
    "Test Part",
resource 'GUID' (130)

To get the custom TBasicPart::SelfDraw() I declared a new class implementing TBasicPart, again following what I found in the modeler sample, perhaps I missed something:

#define R_CLSID_MyPart 0x21c4ac5f, 0x200f, 0x413b, 0xb8, 0xe0, 0xdc, 0xcc, 0x72, 0xdb, 0x6b, 0x1c
extern const MCGUID CLSID_MyPart;
const MCGUID CLSID_MyPart (R_CLSID_MyPart);
class MyPart: public TBasicPart
  public :
  virtual MCCOMErr     MCCOMAPI QueryInterface    (const MCIID &riid, void** ppvObj);
  virtual uint32        MCCOMAPI AddRef() { return TBasicPart::AddRef(); }
  virtual void MCCOMAPI    SelfDraw(IMCGraphicContext* graphicContext, const TMCRect& inZone);
void MyPart::SelfDraw(IMCGraphicContext* graphicContext, const TMCRect& inZone)
  TMCRect theRect;
MCErr MyPart::QueryInterface(const MCIID& riid, void** ppvObj)
  if (MCIsEqualIID(riid, CLSID_MyPart)) 
    TMCCountedGetHelper<MyPart>    result(ppvObj);
    result = this;
    return MC_S_OK;
  return TBasicPart::QueryInterface(riid, ppvObj);
TBasicUnknown* MakeCOMObject (const MCCLSID& classId)
  TBasicUnknown* res = NULL;
  if(classId == CLSID_MyPart)
    res = new MyPart;
  return res;

In response to an event using similar code to raising a dialog box I was then able to add the test node as a child of the main plugin parent's TMFNodePart - the most important code was:

TMCCountedPtr<IMFPart> theTestPart;

Basically the new resource was created and functioned but the ::SelfDraw() was never called, nor was the TBasicUnknown* MakeCOMObject section with the test part.  If I remove the COMP and GUID resource from the (.r) file it still works exactly as if they were never there, suggesting that it's not looking for those.

At least I can see how to dynamically change a UI if I ever need to.

I also tested this using almost the same code above, except to create a window/'Wind' resource in MCSketch and then attach it as a floating window in the main Carrara scene view - which was interesting and one of the other features I was hoping to try.

TMCCountedPtr<IMFPart> theWindow;
Post edited by Sparrowhawke3D on


  • PhilemoPhilemo Posts: 885

    As far as I can't tell, you did it roughly the way I would have done, so it's difficult for me to find a flaw in your code.

    I'm really surprised the MakeComObject was never called. I can't understand how an instance of your class could be created by an other mean... Did you track that through the debugger or by an other mean ?

    It may be a silly question, but why did you use kMFNodeResourceType instead of kMFPartResourceType in the CreatePartByResource call ?

    I'm really interested by the subject. I would gladly need it (that and a functional example for module/modeler :-) ).


  • I did test using kMFPartResourceType and that failed to create anything. theTestPart came back null.  Also there is nothing in MCSketch or anywhere else I can see that is a "part".  Nevertheless it is one of the resources that is listed in enum EMFResources in the MFPartTypes.h.  The other puzzle there is that kMFPartResourceType = 'Part' but the SDK modeler example says to use 'part' with a lower case 'p' and that part of the sample works.  I tried the different combinations in the .r file and even redefined kMFPartResourceType = 'part', with the same results.  Using kMFPartResourceType creates nothing and using kMFNodeResourceType ignores the resource and TBasicPart.

    I set the debugger to run into MakeCOMObject and it only entered once for the main plugin that I was testing this in.

  • PhilemoPhilemo Posts: 885

    So it should be kMFNodeResourceType.

    I checked in dta files found the extension directory and the resource type is indeed 'part' in lowercase.

    By the way, how do you get the reference to the mainNodePart. It may not be active anymore when you add the child. I had a similar issue while trying to set a value in a modifier handle event method. I could find the part, set its value, but it didn't reflect on the GUI because the MC framework had created a new instance of the object and I was updating the old instance.

    An other explanation I could think of is the part size. If the new part size is set to zero, it may not draw anything.

    in MCSKectch, if possible to add a node and change its class name (see the Tab part example).for you, it should be "Test Part". It should be loaded correctly with the interface.


  • I'm testing the test part into an existing modifier using ::HandleEvent() with the case kMsg_CUIP_ComponentAttached for the message though I could also do it with a button response.  To get the mainNodePart of the UI node in the existing plugin I gave it the ID of 'mnde' in MCSketch then I used: 

    if( (sourcePart->FindChildPartByID(&childPart,'prty')==MC_S_OK) && (childPart) )

    Then when I make the new resource a child of that part it shows up just fine but it's not something that I can ::SelfDraw().

    The part size of the node is not zero.  There was some extra code I didn't include in the above post where I repositioned it in the main node UI.

    TMCPoint partpos;


    When I changed the class ID in MCSketch it causes an error "the part TestPart is missing" so I'm pretty sure Carrara will only work with existing types.  I tried to change it to class ID: TMFPart with the same result.  In the class list in the SDK docs are all the IMF's which match with the root classes.  Extra classes like TMF3DUnitEditTextPart with the root class TMFEditTextPart have a corresponding IMFEditTextPart.  There is no IMFNodePart in the list.


    Thanks for those suggestions Philemo.

  • PhilemoPhilemo Posts: 885
    @Sparrowhawke3D I think I eventually found the way of doing it. Tell me if you are still interested in it. If so, I'll post a tutorial as soon as my tests are done.
  • Hi Philemo,

    That would be great if you have found out how to customize the user interface and can explain how you got it to work.  I'd like to dust off that project and try working on it again !

  • head waxhead wax Posts: 6,297

    -wow I love listening to you two talk

Sign In or Register to comment.