'Nth' button press



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

    On 20/05/2012 at 21:17, xxxxxxxx wrote:

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

    ---------
    Hi folks,
     
    how do I get a button message happening for a button that's created in a dynamically added group?
     
    For instance, if a user has added two groups, how do I target the button press coming from the second group?

    //############################################################  
    //--                Dynamic Group Button  
    //############################################################  
    DescriptionCommand *dc_Group_Button = (DescriptionCommand* )data;  
    LONG Button_Group_Button = dc_Group_Button->id[0].id;  
    switch (Button_Group_Button)  
    {  
    case ID_TAB_GROUP_BUTTON:  // I can add +1 here, but this then only actions the ID_TAB_GROUP_BUTTON+1 ID button...  
      {  
      GePrint("nth button pressed...");  
      break;  
      }  
    }
    

    I'm just not sure how to implement the 'nth' button number into the Message() command... I tried experimenting with ID_TAB_GROUP_BUTTON+i (and manually set i=2 just for testing purposes) but it then wouldn't compile because it didn't like the +i being there. Any ideas?
     
    WP



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

    On 21/05/2012 at 07:16, xxxxxxxx wrote:

    When you create buttons dynamically, you usually increase their ID by one. If the Message's ID is within the range of

    (first_button_id - last_button_id) + 1 == n_buttons

    then the "Nth" button pressed is

    pressed_button_id = (message_id - first_button_id)

    Hope that helps. ^^
    Best,
    Niklas



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

    On 22/05/2012 at 05:59, xxxxxxxx wrote:

    Hi Niklas,
     
    thanks for you response. I can now get the "Nth" button press count, but I'm still having troubles getting this to work through the case ID.
     
    If I add the "Nth" button press long number to the ID_TAB_GROUP_BUTTON long then I get a compile error "case expression not constant". So the case isn't like having a variable long added to it.
     
    How do I deal with that part?
     
    EDIT: example of how I was using the nth count number:

    //############################################################  
    //-- Dynamic Group Button  
    //############################################################  
    DescriptionCommand *dc_Group_Button = (DescriptionCommand* )data;  
    LONG Button_Group_Button = dc_Group_Button->id[0].id;
    LONG Button_Number = Button_Group_Button - 4800; // 4800 is the starting ID for the dynamic button  
    switch (Button_Group_Button)  
    {  
    case ID_TAB_GROUP_BUTTON+Button_Number: // compile error here because the ID is not constant
    {  
    GePrint("Button pressed is number " + LongToString(Button_Number));  
    break;  
    }  
    }
    

    WP.



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

    On 22/05/2012 at 06:42, xxxxxxxx wrote:

    Hi WickedP,

    A case statement cannot be an expression in C++, because it is translated into a jump-table (with
    constant addresses => no expressions supported). Use if/else if/else instead. :)

    Best,



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

    On 22/05/2012 at 19:37, xxxxxxxx wrote:

    Aha!
     
    Thanks Niklas! I spent some time yesterday doing some general c++ research on the matter but I wasn't having a very good day yesterday medically so things probably weren't clicking. This morning it makes more sense - and is working!!
     
    For anyone else, working code:

    //############################################################  
    //--                Dynamic Group Button  
    //############################################################  
    DescriptionCommand *dc_Group_Button = (DescriptionCommand* )data;
    LONG Count = Data->GetLong(ID_TAB_GROUP_BUTTON);  // Data = basecontainer data...  
    LONG Button_Group_Button = dc_Group_Button->id[0].id;
    if((Button_Group_Button >= 4801) && (Button_Group_Button <= 4800 + Count))
    {
        GePrint("Button ID press is " + LongToString(Button_Group_Button))
        break;
    }
    else
    {
        break;
    }
    

    EDIT: just something to note for others - be mindful with my code here that the break; in the else{} will prevent other commands from happening that are listed after this button call. So don't use break their if you intend on having other msg elements that come after this in your  code.
     
    Thanks again,
     
    WP.



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

    On 23/05/2012 at 07:24, xxxxxxxx wrote:

    Howdy,

    Just out of curiosity, why not keep count of how many buttons the user has added, and then cycle through them in a for() loop to see which one was clicked?

    Adios,
    Cactus Dan



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

    On 23/05/2012 at 07:38, xxxxxxxx wrote:

    @Cactus: That would be kind of too much, wouldn't it? Do you take a measuring tape and run 4 rounds 'round the career to measure the length of 4 rounds instead of just using simple mathematics?

    Best,
    Nik



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

    On 23/05/2012 at 07:48, xxxxxxxx wrote:

    Howdy,

    Actually no. Cycling through the buttons is VERY fast, so there's no hit on performance.

    For example:

    switch (type)
    {
    	case MSG_DESCRIPTION_COMMAND:
    	{
    		DescriptionCommand *dc = (DescriptionCommand* ) data;
    		LONG i, count = data->GetLong(ID_BUTTON_COUNT);
    		for(i=0; i<count; i++)
    		{
    			if(dc->id[0].id == ID_BUTTON+i)
    			{
    				//process button click
    			}
    		}
    	}
    }
      
    
    

    ... works like a charm.

    Adios,
    Cactus Dan



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

    On 23/05/2012 at 08:27, xxxxxxxx wrote:

    There is a difference in performance, but not noticeable. You'd need to add a lot of thousands of
    buttons to recognize it.
    However, imho this is not an elegant solution. If you have 100 buttons and the User presses the
    last one, you have 99 redundant loops with if-clauses in it.

    Cheers,
    Niklas



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

    On 23/05/2012 at 08:48, xxxxxxxx wrote:

    Howdy,

    Yes that's true. And I would be concerned about that kind of if() statement in a loop if it were in an expression calculation that is called constantly on every refresh. But for a single button click that is a one time call, I wouldn't worry so much about the performance.

    You could add a check to see if the DescriptionCommand is within the buttons' range of maximum allowed buttons:

    switch (type)
    {
    	case MSG_DESCRIPTION_COMMAND:
    	{
    		DescriptionCommand *dc = (DescriptionCommand* ) data;
    		if(dc->id[0].id >= ID_BUTTON && dc->id[0].id < ID_BUTTON+MAX_BUTTON_COUNT)
    		{
    			LONG i, count = data->GetLong(ID_BUTTON_COUNT);
    			for(i=0; i<count; i++)
    			{
    				if(dc->id[0].id == ID_BUTTON+i)
    				{
    					//process button click
    				}
    			}
    		}
    	}
    }
    

    ... so that it's not cycling through the buttons every time the Message() function receives a MSG_DESCRIPTION_COMMAND message. But other than that, I wouldn't be as concerned about it.

    I remember reading an article about code optimization that suggested to optimize only where optimization is needed. So, after reading that article I stopped trying to optimize everything. 😉

    Adios,
    Cactus Dan



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

    On 23/05/2012 at 09:33, xxxxxxxx wrote:

    I really like it when people post their ideas. Even when/if they are not considered "optimal".
    Because after you learn the basics of coding. You spend most of your time searching for approaches to solve a problem.
    Seeing the way other people think helps me to think in ways that I otherwise would not even think about. And for me...seeing how other people approach a problem is where the real value is.
    I often have more questions about how to approach a certain problem. Rather than how to write the actual code for it.
    So please keep posting stuff like this Dan(and everyone). 🍺

    Here's yet another way to do the same thing.
    Not a "better" one. Just a different approach:

    Bool SimpleTag::Message(GeListNode *node, LONG type, void *data)  
    {  
      
      BaseTag *tag = (BaseTag* )node;                //Get the tag and assign it to a variable  
      BaseContainer *bc = tag->GetDataInstance();   //Get the container for the tag  
      
      //BaseContainer *bc = ((BaseList2D* )node)->GetDataInstance(); //Another way of Getting the tag's container  
      
      switch (type)  
        {          
          case MSG_DESCRIPTION_COMMAND:                           //MSG_DESCRIPTION_COMMAND is send when button is clicked  
          {              
              DescriptionCommand *dc = (DescriptionCommand* )data; //Data contains the description ID of the button             
              LONG button = dc->id[0].id;                         //Get the ID of the button that's pressed  
          GePrint("Button id= " + LongToString(button));      //prints the button's ID number  
          LONG nth = button - 1001;                           //Gets the nth button value in the list of buttons(assuming that the first button's ID value is 1002)  
          GePrint("Nth Button " + LongToString(nth));  
                            
              switch (button) // check for different button IDs  
              {  
                  case BUTTON1:  
                      GePrint("Button1 was pushed");  
                      bc->SetReal(MYNUMERIC, index+1);  //Adds a new slider to the tag  
                      break;  
      
                  case BUTTON2:  
                      GePrint("Button2 was pushed");  
                      break;  
              }  
          }  
        }  
       
      tag->SetDirty(DIRTYFLAGS_DATA); //Used to update a Tag's AM GUI items  
      return TRUE;  
    }
    

    -ScottA



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

    On 23/05/2012 at 09:41, xxxxxxxx wrote:

    Howdy,

    Just as the old saying goes, "There's more than one way to skin a cat." 😉

    Adios,
    Cactus Dan


Log in to reply