HandleShaderPopupI() & BuildShaderPopupMenuI()



  • On 12/01/2017 at 00:07, xxxxxxxx wrote:

    Hello,

    ShowPopupMenu() does not return a Boolean value. It returns a Int32 value, storing the ID of the selected element.

    best wishes,
    Sebastian



  • On 12/01/2017 at 08:16, xxxxxxxx wrote:

    Oops. Sorry about that.
    I didn't mean to include ShowPopupMenu() in that Bool category.

    I'm having some difficulty making your example code work in my scenario. Because in your example ShowPopupMenu() is a new instance of the menu. But in my plugin I'm using the built-in menu. And I don't know how to get a pointer to that existing menu. And get what the user clicked.
    Using ShowPopupMenu() to get the existing menu seems wrong to me because I don't want to launch that menu with code. I just want to use the one that's already there.

    In short.
    Using the built-in popup menu in a MaterialData plugin requires different parameter values than the example code you posted. And I'm having difficulties figuring out.
    I'll keep on trying.

    Here's some code showing what I'm doing.

    INITRENDERRESULT ExampleMaterial::InitRender(BaseMaterial* mat, const InitRenderStruct& irs)  
    {  
      
      //Build the items of the popup menu here locally in code using the BuildShaderPopupMenuI()  
      BaseContainer shaderList;  
      BaseShader *shader = nullptr;  
      BuildShaderPopupMenuI(&shaderList, mat, shader, SHADERPOPUP_SETSHADER);  
      
      //Now lets loop through the shaderList container to get the popup item values   
      LONG index = 0;  
      while (shaderList.GetIndexId(index) != NOTOK)  
      {  
          LONG id = shaderList.GetIndexId(index);  
      
          GeData data = shaderList.GetData(id);  
          GePrint("id String: " + LongToString(id) + " = " + data.GetString());  
      
          index++;  
      }  
      
      //I don't want to build a new popup list, so I don't want to use ShowPopupMenu()  
      //I want to use the existing popup menu  
      //So I try to use it like this. But it doe not work        
      if (HandleShaderPopupI(mat, shader, 5832, 0)) //<--- If the color item was selected  
      {  
          GePrint("Color type shader was added");   //<---Does not work!   
      }  
      
      return INITRENDERRESULT_OK;  
    }
    

    If I must use the ShowPopupMenu() function. Then that's a problem, because I don't see any way of getting the mouse coords from inside of a MaterialData plugin.

    -ScottA

    *Edit-
    The more time I spend on this. The more I'm thinking that HandleShaderPopupI() only works with a custom built menu. And does not work with the existing ones.
    I have no idea if HandleShaderPopup() is any different. Because I can't get that one to work either.



  • On 13/01/2017 at 00:40, xxxxxxxx wrote:

    Hello,

    BuildShaderPopupMenuI() fills a BaseContainer with the shader list, ShowPopupMenu() displays that list as a popup menu, HandleShaderPopupI() takes the result of the interaction with that menu and provides access to the associated shader. This has nothing to do with MaterialData plugins.

    What do you mean with "built-in popup menu"? Are you talking about a shader-link parameter? If you want to check if such a parameter was changed you have to implement SetDParameter().

    best wishes,
    Sebastian



  • On 13/01/2017 at 07:54, xxxxxxxx wrote:

    Yes.
    The more time I spent on this, the more I realized that these functions in question were for a special case usage for generating the shader popup list. And we must use them together as a group. Meaning that we must use ShowPopupMenu() with them. Which is not what I want to do.
    I just wanted to handle the click event message that occurs on the existing MaterialData shader link popup list.

    I'll try using the SetDParameter() next. But that method is not listed as a supported overridden method in the docs for this kind of plugin. So I assumed it was not even an option.
    If it works, then it must work through inheritance.

    I'll give it try.
    Thanks,
    -ScottA

    Update:
    As I feared. According to my notes and the doc. SetDParameter() is only for node based plugins. And does not work in MaterialData plugins.
    When Maxon wrote their Materials code. Someone at the company used the ShowPopupMenu() method to make the shader pop list open when the little arrow button is pressed by the user.
    What I need is the variable name they assigned to it. Then I can simply get the Long result from it to know which item the user selected.
    Is there any way for us to get the value of that variable?



  • On 16/01/2017 at 00:54, xxxxxxxx wrote:

    Hello,

    MaterialData is based on NodeData so you can implement SetDParameter().

    best wishes,
    Sebastian



  • On 16/01/2017 at 07:58, xxxxxxxx wrote:

    Getting closer. But still not quite there.

    Bool ExampleMaterial::SetDParameter(GeListNode *node, const DescID &id, const GeData &t_data, DESCFLAGS_SET &flags)  
    {  
      if (!node) return false;  
      
      //GePrint(LongToString(id[0].id));   //Prints 2003 when any of the shader popup list items are selected  
      
      switch (id[0].id)  
      {  
          case 2003:  
          {              
              LONG value = t_data.GetLong();  
              GePrint(LongToString(value));   //<---Always returns 0  
      
              //How do I get the item the user clicked???  
      
              //Mark the parameter as set  
              flags |= DESCFLAGS_SET_PARAM_SET;  
      
              //Return from the function, don't call the function of the base class.  
              return true;              
          }break;  
      }  
      return SUPER::SetDParameter(node, id, t_data, flags);  
    }
    

    -ScottA



  • On 16/01/2017 at 23:48, xxxxxxxx wrote:

    Hello,

    a shader-link parameter stores a BaseLink to a BaseShader.

      
    BaseLink* link = t_data.GetBaseLink();  
    if (link)  
    {  
      BaseList2D* shader = link->ForceGetLink();  
      if (shader)  
      GePrint(shader->GetName());  
    }  
    

    best wishes,
    Sebastian



  • On 17/01/2017 at 07:34, xxxxxxxx wrote:

    Thanks. ForceGetLink() was the thing I was missing.
    But isn't this code doing the same thing as I posted in Post#3. Only with slightly different code?

    In this code, and the code in post#3. The code is getting the shader object that resides in the link.
    That object gets created based on what popup item the user clicked.
    But what I was originally wondering how to do is get the popup item's name(or ID#) when one of the popup items is selected. Before it actually creates anything.
    Not getting the item clicked by getting the shader object it created.

    In the code you posted in the other thread. We can get that value from res (the variable assigned to ShowPopupMenu()).
    But I'm still wondering if/how we can do the same thing with the existing popup shader menu?
    Is that possible?

    -ScottA



  • On 18/01/2017 at 00:29, xxxxxxxx wrote:

    Hello,

    you cannot access the "existing popup shader menu". You MaterialData plugin may include a shader-link parameter. This parameter is presented in the Attribute Manager or Material Manger with some GUI. This GUI internally uses that Pop-Up menu, but only for internal purposes to set the shader. One might create a custom GUI for shader-link parameters that works differently. A material should typically not care about how the parameter is set but to what value it is set.

    best wishes,
    Sebastian



  • On 18/01/2017 at 07:23, xxxxxxxx wrote:

    OK. Thanks.
    I have a much better understanding of what's happening with that popup menu now.
    And the ForceGetLink() code was something missing from my notes too.

    Here's my code in case anyone needs it:

    Bool MyMaterial::SetDParameter(GeListNode *node, const DescID &id, const GeData &t_data, DESCFLAGS_SET &flags)  
    {  
      if (!node) return false;  
      
      switch (id[0].id)  
      {  
          //2003 is the ID sent when the shader popup list pops up  
          case 2003:  
          {  
              BaseLink *link = t_data.GetBaseLink();  
              if (link)  
              {  
                  BaseList2D* shader = link->ForceGetLink();  
                  if (shader) GePrint(shader->GetName());  
              }              
                
              //Use this only if you want to override the shader being created to something else  
              //For the default shader popup list this would not make much sense  
              //flags |= DESCFLAGS_SET_PARAM_SET;  
       
              return true;              
          }break;  
      }  
      return SUPER::SetDParameter(node, id, t_data, flags);  
    }
    

    -ScottA


Log in to reply