Dialogs and Event Handlers

SighmanSighman Posts: 56
edited December 1969 in Carrara SDK Developer Discussion

I hope this is a simple question to answer...

I have created a dialog but I want to be able to respond to events such as clicking on buttons, etc. I see that there is an IMFResponder interface but I'm not sure if I need to implement it or inherit from something. I'm also not sure how to wire up the event handler.


TMCCountedPtr dialog;
gPartUtilities->CreatePartByResource(&dialog;, kMFDialogResourceType, 128);
ThrowIfNil(dialog);

TMCCountedPtr dialogPart;
dialog->QueryInterface(IID_IMFDialogPart, (void**)&dialogPart;);
ThrowIfNil(dialogPart);

IMFWindow* window = dialogPart->GetThisWindow();

// How do I add an event handler?
// window->SetWindowFirstResponder(responder) ???     
   
dialogPart->Go(); // opens the dialog

dialogPart->Finished();

Comments

  • Eric WinemillerEric Winemiller Posts: 84
    edited December 1969

    Hey Simon,

    It's been a long time since I played with this, but I think it's easier than it seems.

    I do this on the Anything Grows modifier. The basic controls are there and there's an Advanced button that takes you to the full UI.

    The Advanced button is a TMFDialogButtonPart. Its Dialog ID = 310, which just happens to be the Node for the Grows primitive UI. User clicks on button, magic happens, you get a dialog.

    All the events get routed through your original object's HandleEvent.

    I can reference the all the controls on the dialog just like they were part of my usual UI. Example below. When I detect the Advanced button is clicked I hide the stuff that doesn't apply to the Modifier and fill all the combos.

    There's nothing special to write, just a button on your original UI, a node for your dialog, and override HandleEvent from TBasicDataExchanger.

        
    
    if ((message == kMsg_CUIP_ComponentAttached)||((sourceID == 'ADVA')&&(message == EMFPartMessage::kMsg_PartValueChanged))) {
            TMCCountedPtr popuppart;
            TMCCountedPtr primcomp;
            TMCCountedPtr object;
            TMCCountedPtr prim;
            TMCCountedPtr instance;
    
            HidePart(sourcePart, sourceID, 'RMSL');
            HidePart(sourcePart, sourceID, 'PREV');
            HidePart(sourcePart, sourceID, 'LINE');
            HidePart(sourcePart, sourceID, 'OBJS');
            HidePart(sourcePart, sourceID, 'OBJP');
            HidePart(sourcePart, sourceID, 'OBJL');
    
            //reference object list
            if (sourceID == 0) {
                sourcePart->FindChildPartByID(&popuppart;, IDTYPE('R','E','F','P'));
                }
            else {
                TMCCountedPtr parentPart;
                sourcePart->GetPartParent(&parentPart;);
                parentPart->FindChildPartByID(&popuppart;, IDTYPE('R','E','F','P'));
                }
            if (tree != NULL)
            {
                tree->QueryInterface(IID_I3DShInstance, (void**)&instance;);
                if (popuppart != NULL)
                {
                    FillObjectList(NULL, instance, popuppart);
                }
            }
    ... 
    

    Regards,

  • SighmanSighman Posts: 56
    edited December 1969

    Great information Eric, just what I was looking for.

    Your code makes reference to a 'tree' variable that you use to get the instance. How did you initialize that from within the event handler? The only thing I can think of, because of all the cloning, is to set a static variable in the IsActive method.

  • Eric WinemillerEric Winemiller Posts: 84
    edited December 1969

    In this case I'm a modifier so I can get out out to my tree like so from DeformFacetMesh which gets called before the UI ever gets shown. It might work from inside HandleEvent. I don't remember if I tried. However sometimes there's goofiness where one object is instanced to do the work and a clone handles the UI. Based on the overridden Clone method I see in there (where I copy the scene and tree) I suspect that is the case with modifiers. You have to capture it before the UI clone is made and copy it in your Clone method.

    
    MCCOMErr AnythingGrowsDeformer::DeformFacetMesh(real lod,FacetMesh* in, FacetMesh** outMesh) 
    {
     TMCCountedPtr Member;
    
     if (TBasicModifier::QueryInterface(IID_I3DShTreeElementMember, (void**)&Member;) == MC_S_OK) 
     {
      Member->GetTreeElement(&tree;);
    
    

    In what kind of object do you need to find the tree? I've built nearly one of each so I might have the specifics for what you're doing too.

    Regards,

  • SighmanSighman Posts: 56
    edited December 1969

    I am trying to find the instance for a Data Component (Effect).

  • Eric WinemillerEric Winemiller Posts: 84
    edited December 1969

    For a data component, I grab it from overriding TBasicDataComponent::IsActive and copy it in Clone. Don't use a static.

    
    boolean  ToonEnabled::IsActive(I3DShTreeElement* tree)
    {
     this->tree = tree;
     return true;
    }
    
    void ToonEnabled::Clone(IExDataExchanger**res,IMCUnknown* pUnkOuter)
    {
     TMCCountedCreateHelper result(res);
     ToonEnabled* clone = new ToonEnabled(static_cast(lRenderStyle));
     result = (IExDataExchanger*)clone;
    
     clone->CopyDataFrom(this);
    
     clone->SetControllingUnknown(pUnkOuter);
    }
    
    void ToonEnabled::CopyDataFrom(const ToonEnabled* source)
    {
     toonSettings = source->toonSettings;
     tree = source->tree;
     fData = source->fData;
    }
    

    Regards,

  • SighmanSighman Posts: 56
    edited December 1969

    Works like a charm. Thanks.

Sign In or Register to comment.