R12 PrefsDialogHook/PrefsDialogObject/etc.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 12/09/2010 at 07:57, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   R12 
Platform:   Windows  ;   Mac OSX  ; 
Language(s) :     C++  ;

---------
Example of correct usage, please? This area has been completely rewritten, and yet remains undocumented, not even being mentioned in the transition PDF.

JD

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 13/09/2010 at 00:33, xxxxxxxx wrote:

The documentation is currently preliminary and will be updated soon. If I find the time I will try to post a small example later today.

cheers,
Matthias

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 13/09/2010 at 06:37, xxxxxxxx wrote:

Thanks. For most of the changes, documentation is hardly even necessary, but I'd prefer not to spend alot of time blindly poking around this particular black box.

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 14/09/2010 at 03:32, xxxxxxxx wrote:

Basically all that is needed now for plugin preference hooks is your own overloaded PrefsDialogObject class. As you may have noticed preferences are description based in R12 and derived from NodeData.

Here an example from our timeline prefs which should get you started. There are still some things unclear to myself but currently the developer responsible for the prefs overhaul is on vacation. I will keep you posted.

  
class TimelinePrefsObject : public PrefsDialogObject  
{  
  INSTANCEOF(TimelinePrefsObject,PrefsDialogObject)  
  public:  
      static NodeData *Alloc() { return gNew TimelinePrefsObject; }  
  
      virtual Bool GetDDescription(GeListNode *node, Description *description, DESCFLAGS_DESC &flags);  
      virtual Bool GetDParameter(GeListNode *node, const DescID &id,GeData &t_data,DESCFLAGS_GET &flags);  
      virtual Bool SetDParameter(GeListNode *node, const DescID &id,const GeData &t_data,DESCFLAGS_SET &flags);  
      virtual Bool GetDEnabling(GeListNode *node, const DescID &id,const GeData &t_data,DESCFLAGS_ENABLE flags,const BaseContainer *itemdesc);  
      virtual Bool Init(GeListNode* node);  
      virtual Bool InitValues(const DescID &id, Description* desc = NULL);  
        
  private:  
      BaseContainer* GetTLPrefs();  
};  
  
// My own function to get the TL containmer from the world prefs  
BaseContainer* TimelinePrefsObject::GetTLPrefs()  
{  
  BaseContainer* bc=GetWorldContainerInstance()->GetContainerInstance(PREFSDIALOG_ID);  
  if (!bc)  
  {  
      GetWorldContainerInstance()->SetContainer(PREFSDIALOG_ID,BaseContainer());  
      bc = GetWorldContainerInstance()->GetContainerInstance(PREFSDIALOG_ID);  
      if (!bc) return NULL;  
  }  
  
  return bc;  
  
}  
  
// Return the Parameter --> make sure to always set the flag  
Bool TimelinePrefsObject::GetDParameter(GeListNode *node, const DescID &id,GeData &t_data,DESCFLAGS_GET &flags)  
{  
  BaseContainer* bc = GetTLPrefs();  
  if (!bc) SUPER::GetDParameter(node,id,t_data,flags);  
  
  switch (id[0].id)  
  {  
      case PREF_TL_HIGHLIGHT:  
          t_data = bc->GetBool(WPREFS_HIGHLIGHT,TRUE);  
          flags |= DESCFLAGS_GET_PARAM_GET;  
          return TRUE;  
            
      // ...  
  }  
  return SUPER::GetDParameter(node,id,t_data,flags);  
}  
  
// Enable and disable the parameters  
Bool TimelinePrefsObject::GetDEnabling(GeListNode *node, const DescID &id,const GeData &t_data,DESCFLAGS_ENABLE flags,const BaseContainer *itemdesc)  
{  
  BaseContainer* bc = GetTLPrefs();  
  if (!bc) SUPER::GetDEnabling(node,id,t_data,flags,itemdesc);  
    
  return SUPER::GetDEnabling(node,id,t_data,flags,itemdesc);  
}  
  
// Set the parameters -> make sure to always set the flag and call GeUpdateUI()  
Bool TimelinePrefsObject::SetDParameter(GeListNode *node, const DescID &id,const GeData &t_data,DESCFLAGS_SET &flags)  
{  
  BaseContainer* bc = GetTLPrefs();  
  if (!bc) SUPER::SetDParameter(node,id,t_data,flags);  
  
  switch (id[0].id)  
  {  
      case PREF_TL_HIGHLIGHT:  
          bc->SetBool(WPREFS_HIGHLIGHT,t_data.GetLong());  
          flags |= DESCFLAGS_SET_PARAM_SET;  
          GeUpdateUI();  
          return TRUE;  
    
  }  
    
  return SUPER::SetDParameter(node,id,t_data,flags);  
}  
  
// Init the values  
Bool TimelinePrefsObject::Init(GeListNode* node)  
{  
  BaseContainer* bc = GetTLPrefs();  
  if (!bc) return FALSE;  
    
  InitPrefsValue(WPREFS_HIGHLIGHT,GeData(TRUE),desc,id,bc);  
  // do this for all values  
  
  return TRUE;  
}  
  
// Set the description and if the flag DESCFLAGS_DESC_NEEDDEFAULTVALUE was set the user called reset to Parameter  
Bool TimelinePrefsObject::GetDDescription(GeListNode *node, Description *description, DESCFLAGS_DESC &flags)  
{  
  if (!description->LoadDescription("Prefstimeline")) return FALSE;  
  
  if ( flags & DESCFLAGS_DESC_NEEDDEFAULTVALUE )  
  {  
      InitPrefsValue(WPREFS_HIGHLIGHT,GeData(TRUE),desc,id,bc);  
      // do this for all values  
  }  
  
  flags |= DESCFLAGS_DESC_LOADED;  
  return SUPER::GetDDescription(node, description, flags);  
}  
  
  
// Register  
Bool RegisterPrefs()  
{  
  PrefsDialogObject::Register(PREFS_TL,TimelinePrefsObject::Alloc,GeLoadString(IDS_TL_TITLEPREFS),"Prefstimeline",0,PREFS_PRI_MODULES);  
  return TRUE;  
}  

cheers,
Matthias

THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

On 15/09/2010 at 20:45, xxxxxxxx wrote:

Thanks for posting the example. Just fyi, there are some mistakes (i.e. missing 'return' @ [if (!bc) SUPER::] in a few methods, and phantom desc/id params being used in Init/GetDDescription), so maybe the post should be edited, to protect against copy/paste coders.

Also, I have no idea what those InitPrefsValue methods are supposed to be doing -- they didn't seem to affect anything at all here.

So, in case anyone else wonders how to make it work: as I was previously doing with the old dialog-based prefs hook, and as you are basically doing here, I just put a BaseContainer into the world container and use Set/GetDParameter to forward UI action to/from that.

Rather than messing around with those InitNnn methods though, I just initialize everything in the BaseContainer on first access, or on DESCFLAGS_DESC_NEEDDEFAULTVALUE. So basically:

Bool TimelinePrefsObject::GetTLPrefs(BaseContainer*& bc)
{    
    bc = GetWorldContainerInstance()->GetContainerInstance(PREFSDIALOG_ID);
   
    if (!bc)    
    {       
        GetWorldContainerInstance()->SetContainer(PREFSDIALOG_ID,BaseContainer());       
        bc = GetWorldContainerInstance()->GetContainerInstance(PREFSDIALOG_ID);
       
        // no prefs, init values
        if (bc) InitContainer(bc);
    }

return bc != 0;
}

Whatever the case, the new system is much better than the old one -- only one object to deal with, and besides that, descriptions just work alot nicer.