Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Iterate

    PYTHON Development
    0
    38
    24.4k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 04/06/2017 at 04:37, xxxxxxxx wrote:

      Yes! This works! I have a question, though. The code below will reset everything within the group without hardcoding individual userdatas. I would like to avoid that as there are so many. Can this be done?

      for id, bc in obj.GetUserDataContainer() :    
                  if bc[c4d.DESC_PARENTGROUP][-1].id == 284: # G_Vegas Group
                      try:
                          obj[id] = bc[c4d.DESC_DEFAULT]
                      except TypeError:
                          pass
      
      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 04/06/2017 at 04:42, xxxxxxxx wrote:

        There are 16 user data variables for each of 10 presets and there are 10 sets of presets so I am looking at hardcoding 1600 userdatas. I would like to avoid that if possible and just use the Group user data id so that everything within the group is reset. Also, this way if I add to the group, I don't have to worry about the code missing that parameter because I didn't reference its specific ID.

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 04/06/2017 at 08:52, xxxxxxxx wrote:

          Originally posted by xxxxxxxx

          I never said that it was the proper solution to use Niklas.
          I merely answered his question on "if there was a way to target a specific UD item without using a loop".
          I never told him to use it. Nor did I tell him it was a better solution than yours.

          -ScottA

          You posted your answer without any information on potential
          issues or limitations, thus I must assume that you either do not
          know them or forgot to include them in your answer.

          Either way, I feel obliged to point out that your answer only
          works in a special case, namely when you create the userdata
          sequentially and do not modify it afterwards.

          If you answer a question without the intend of someone using
          the information from your answer, why answer it at all.

          -Niklas

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 04/06/2017 at 12:00, xxxxxxxx wrote:

            Who the hell do you think you are Niklas?
            And where do you get off talking to me in such a manner?
            He asked a question. I even quoted it for clarity. Then I gave him the answer to that question.
            He asked a specific question. And I gave him a specific answer. That's SOP.
            It's not your place to give your almighty approval on how to answer someone's question.

            I've managed hundreds of people and several business for over three decades. And some 20 something yr old snot nosed punk on the internet with the ego the size of 747 who thinks he's God's gift to coding is going to tell me how to properly reply to a question?
            Oh hell no.
            You weren't even an idea when I was managing people for a living.
            Seriously. Who the hell do you think you are talking to me in that way?
            That was way out of line.

            -ScottA

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 04/06/2017 at 16:36, xxxxxxxx wrote:

              Originally posted by xxxxxxxx

              Who the hell do you think you are Niklas?
              And where do you get off talking to me in such a manner?
              He asked a question. I even quoted it for clarity. Then I gave him the answer to that question.
              He asked a specific question. And I gave him a specific answer. That's SOP.
              It's not your place to give your almighty approval on how to answer someone's question.

              I've managed hundreds of people and several business for over three decades. And some 20 something yr old snot nosed punk on the internet with the ego the size of 747 who thinks he's God's gift to coding is going to tell me how to properly reply to a question?
              Oh hell no.
              You weren't even an idea when I was managing people for a living.
              Seriously. Who the hell do you think you are talking to me in that way?
              That was way out of line.

              -ScottA

              Dear Scott, I am sorry if you feel personally assaulted. My intentions are solely directed at improving
              accuracy of information in this thread. I do not want to further derail this thread, so if you feel like
              continuing this discussion, I invite you to contact me via PM.

              Regards,
              -Niklas

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 04/06/2017 at 17:46, xxxxxxxx wrote:

                Is there a way instead of using the tuple to just use the group user ID and some code that refers to what's under it instead of hardcoding what's under it? That would solve the problem.

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 04/06/2017 at 19:10, xxxxxxxx wrote:

                  @Niklas.
                  Thank you for apologizing.
                  We're cool. But wow man. Take it easy on that whole "correction" stuff.
                  I'm not exactly a rookie at this. I've been here longer than you and the last thing I need is posting lessons from you. So cut the crap dude. Or I'll swim over there and kick you're little butt. 😉
                  Lets just shake hands and put it behind us.

                  -ScottA

                  1 Reply Last reply Reply Quote 0
                  • H
                    Helper
                    last edited by

                    On 05/06/2017 at 02:40, xxxxxxxx wrote:

                    This code resets all the UD under it.

                    for id, bc in obj.GetUserDataContainer() :    
                                if bc[c4d.DESC_PARENTGROUP][-1].id == 284: # G_Vegas Group
                                    try:
                                        obj[id] = bc[c4d.DESC_DEFAULT]
                                    except TypeError:
                                        pass
                    

                    Can this somehow be incorporated into this?

                    import c4d
                      
                    #dict who gonna store all our bc and descid. Like that we iterate only 1 time.
                    #dict["user_data_id"] = [descid, bc]
                    #I use global vairable liek that we only have to do build it one time.
                    #take care if you add/remove ud you need to update it, look the main function
                    global dict_descid_bc
                    dict_descid_bc = None
                      
                    def reset(obj, id_reset, list_id) :
                        global dict_descid_bc
                        ud_bc = obj.GetUserDataContainer()
                        
                        #Only if reset is True
                        if obj[c4d.ID_USERDATA, id_reset]:
                            obj[c4d.ID_USERDATA, id_reset] = False
                            #We list all our id who are into our list_of_id_to_reset
                            for id in list_id:
                                if id == id_reset:
                                    continue
                                
                                descid = dict_descid_bc[id][0]
                                bc = dict_descid_bc[id][1]
                                try:
                                    obj[c4d.ID_USERDATA, id] = bc[c4d.DESC_DEFAULT]
                                except:
                                    pass
                                        
                    def get_descid_bc(obj, dict) :
                        for descid, bc in obj.GetUserDataContainer() :
                            dict[descid[-1].id] = [descid, bc]
                                        
                                
                    def main() :
                        #Get the object attached ot the tag
                        obj = op.GetObject()
                        
                        #Tell to python we use the global variable
                        global dict_descid_bc
                        
                        #Only update our dict if not built yet.
                        if not dict_descid_bc:
                            dict_descid_bc = dict()
                            get_descid_bc(obj, dict_descid_bc)
                        
                        #list who store all our data
                        #Reset_id, List_of_id_to_reset, list_of_descid_bc
                        datas = list()
                      
                        #Data exemple for G_Vegas
                        tupe_G_vegas = (486, 15, 17, 4, 44, 42, 27, 28, 512, 36, 29, 393, 38, 39, 40, 19, 389)
                        datas.append([486, tupe_G_vegas ])
                      
                        #Loop for each data then reset them
                        for data in datas:
                            reset(obj, data[0], data[1])
                            
                        #Trigger c4d update
                        c4d.EventAdd()
                      
                      
                    if __name__ == '__main__':
                        main()
                    
                    1 Reply Last reply Reply Quote 0
                    • H
                      Helper
                      last edited by

                      On 06/06/2017 at 01:41, xxxxxxxx wrote:

                      Since I seriously doubt you try to understand code, I don't comment my code. But fel free to ask 😉

                      import c4d
                        
                      def reset(obj, group_id) :
                          for descid, bc in obj.GetUserDataContainer() :
                              if bc[c4d.DESC_PARENTGROUP][-1].id in group_id:
                                  try:
                                      obj[descid] = bc[c4d.DESC_DEFAULT]
                                  except:
                                      pass
                        
                      def get_group_to_get(obj, datas) :
                          buffer = list()
                          for i in xrange(len(datas)) :
                              if obj[c4d.ID_USERDATA, datas[i][0]]:
                                  obj[c4d.ID_USERDATA, datas[i][0]] = False
                                  buffer.append(datas[i][1])
                        
                          return buffer
                        
                        
                      def main() :
                          # Get the object attached ot the tag
                          obj = op.GetObject()
                        
                          #list of list[enable_id, group_id]
                          datas = [[486, 284],
                                   ]
                        
                          group_to_check = get_group_to_get(obj, datas)
                          if not group_to_check:
                              return
                        
                          #Reset data
                          reset(obj, group_to_check)
                        
                        
                        
                          # Trigger c4d update
                          c4d.EventAdd()
                        
                        
                      if __name__ == '__main__':
                          main()
                      
                      1 Reply Last reply Reply Quote 0
                      • H
                        Helper
                        last edited by

                        On 06/06/2017 at 02:02, xxxxxxxx wrote:

                        I would still suggest to retrieve the UserData once and store it globally, to avoid calling
                        GetUserDataContainer() multiple times. Converting it to a dictionary reduces the time
                        searching for an entry with a specific ID immensely.

                        import c4d
                          
                        # A dictionary that stores the object's UserData where the keys
                        # are the UserData ID's and the values are the (DescID, BaseContainer)
                        # pairs returned by GetUserDataContainer()
                        ud = None
                          
                        def main() :
                            obj = op.GetObject()
                            
                            # We could also do this once really (if ud is None: ...) but it
                            # would make development harder since the tag would need to be
                            # "refreshed" everytime you change the userdata. It's still a LOT
                            # better than using GetUserDataContainer() multiple times and it
                            # also enhances search times for entries with specific IDs.
                            global ud
                            ud = dict((dd[-1].id, (dd, bc)) for dd, bc in obj.GetUserDataContainer())
                          
                            # ...
                          
                        def reset(obj, group_id) :
                            for dd, bc in ud.itervalues() :
                                if bc[c4d.DESC_PARENTGROUP][-1].id in group_id:
                                    try:
                                        obj[dd] = bc[c4d.DESC_DEFAULT]
                                    except TypeError:
                                        pass
                        

                        To look up an entry with a spefic ID, you'd just use the ud Dictionary.

                        def main() :
                            # ...
                          
                            desc_id, bc = ud[4]  # Get's DescID and item description of userdata with ID 4
                        

                        On a side note, you will loose the order of the items returned by GetUserDataContainer(). But it
                        appears that you do not need it anyway.

                        -Niklas

                        1 Reply Last reply Reply Quote 0
                        • H
                          Helper
                          last edited by

                          On 06/06/2017 at 02:46, xxxxxxxx wrote:

                          Thank-you Niklas and gr4ph0s for this code. It is greatly appreciated.

                          1 Reply Last reply Reply Quote 0
                          • H
                            Helper
                            last edited by

                            On 06/06/2017 at 02:54, xxxxxxxx wrote:

                            But since op don't want to hardcode his user_id he will still need to iterate thourght the dictionary each time so it will be same as iterate GetUserDataContainer.

                            So it's why in my previous method, in all case even if there is 3 reset On, it will iterate only one time.

                            EDIT: a nicer way would be to get UserDataContainer only one time for build a dict with parent/child relation dict["parent_id]:[descid,bc] then store this dict globally.
                            And finally do as I did in my previous post but using dict instead.

                            1 Reply Last reply Reply Quote 0
                            • H
                              Helper
                              last edited by

                              On 06/06/2017 at 03:07, xxxxxxxx wrote:

                              Originally posted by xxxxxxxx

                              But since op don't want to hardcode his user_id he will still need to iterate thourght the dictionary each time so it will be same as iterate GetUserDataContainer.

                              It is not the same because GetUserDataContainer() needs to build the list from the object's
                              DynamicDescription first, which is an overhead you  only have once instead of each time you
                              use the function if you cache the result instead (either directly or as a dictionary, doesn't matter
                              very much).

                              1 Reply Last reply Reply Quote 0
                              • H
                                Helper
                                last edited by

                                On 06/06/2017 at 07:02, xxxxxxxx wrote:

                                Hi,

                                sorry to interrupt the professional discussion once more.

                                I was a bit surprised, when returning after a long weekend, to see this thread completely derailed and two long term community members ranting at each other.

                                Looks like you already settled this, but just in case you didn't and you are still throwing bombs at each other via PM, please, reach your virtual hands. I'm pretty sure, nobody wanted to insult anybody and we shouldn't get on a personal level in this forum.

                                Of course insults on a personal level are generally a no-go in this forum. And here I have to say, Scott, you went a bit overboard for no obvious reasons.

                                One more thing to clarify:
                                We want to have this forum as a source of information. And therefore it is absolutely necessary to discuss proposed solutions and also mention their shortcomings. Critique and corrections are the base for good solutions. And it's not that far fetched to assume, a post in a thread is also meant as a solution to the actual problem. So for me, Niklas was right to point out possible problems. We can not expect a future reader to implicitly notice these all by himself.

                                So, if not already done so, exchange a PM apologizing to each other.

                                And now I step back again and let you guys optimize the code further.

                                1 Reply Last reply Reply Quote 0
                                • H
                                  Helper
                                  last edited by

                                  On 06/06/2017 at 09:08, xxxxxxxx wrote:

                                  ^#!$#!**t Andreas.
                                  This is the second time where you took the side of Niklas for attacking me for no good reason. And then had the gall to publicly lecture me as if I was actually in the wrong.
                                  And the second time where after I took the high road said ok never mind. Lets just drop it, and chalk it up to a misunderstanding. You then came back again and took another cheap shot at me for no good reason other than to get in one more dig at me.
                                  Since it was "Settled". Your involvement in this thread was completely unnecessary Andreas.
                                  But worse than that. You had the balls to point at me for defending myself from being attacked for no good reason by another member who was obviously completely out of line.

                                  Since you obviously have some major bias with Niklas. And not only allow him to attack people, but actually support it and take his side when he does it. I'm no longer going to participate in this forum.
                                  This is no longer the casual, ego free, easy going place, where developers can not only help each other out, but also talk comfortably with each other. Without worrying about being jumped on for asking simple questions. Or having a different opinion.
                                  This place is now a cold and harsh environment. Where massive egos are bowed to, and treated like Gods. And are actually encouraged to be rude and arrogant to other members who are considered to be "below their standards".
                                  There's no humans here anymore. Just robots that have no clue how to have a Human-To-Human conversation. And I have no need, or desire, to be in that kind of environment.
                                  That's probably why all the old timers don't post here anymore. This place has been infected with too many bloated egos.

                                  Shame on you. Shame on you both.
                                  You've ruined one of my favorite places to talk with developers. And turned it into StackOverflow 2.0.

                                  -ScottA

                                  Edit: Admin removed profanity

                                  1 Reply Last reply Reply Quote 0
                                  • H
                                    Helper
                                    last edited by

                                    On 06/06/2017 at 09:38, xxxxxxxx wrote:

                                    I have tested gr4ph0s last code against my initial code. I didn't implement Niklas' changes because I don't know how. Both clock in a 3 sec in the main (more complex) file. So they both appear to be taking the same time to accomplish the same task. Any idea why this may be the case?

                                    1 Reply Last reply Reply Quote 0
                                    • H
                                      Helper
                                      last edited by

                                      On 06/06/2017 at 10:24, xxxxxxxx wrote:

                                      Here is what I am running:

                                      import c4d
                                        
                                      def reset(obj, group_id) :
                                          for descid, bc in obj.GetUserDataContainer() :
                                              if bc[c4d.DESC_PARENTGROUP][-1].id in group_id:
                                                  try:
                                                      obj[descid] = bc[c4d.DESC_DEFAULT]
                                                  except:
                                                      pass
                                        
                                      def get_group_to_get(obj, datas) :
                                          buffer = list()
                                          for i in xrange(len(datas)) :
                                              if obj[c4d.ID_USERDATA, datas[i][0]]:
                                                  obj[c4d.ID_USERDATA, datas[i][0]] = False
                                                  buffer.append(datas[i][1])
                                        
                                          return buffer
                                        
                                        
                                      def main() :
                                          # Get the object attached ot the tag
                                          obj = op.GetObject()
                                        
                                          #list of list[enable_id, group_id]
                                          
                                          #G
                                          datas = [[486, 284],
                                                  [485, 285],
                                                  [489, 287],
                                                  [490, 289],
                                                  [491, 291],
                                                  [492, 293],
                                                  [508, 295],
                                                  [509, 297],
                                                  [510, 299],
                                                  [511, 301],
                                                  
                                                  #S1
                                                  [561, 558],
                                                  [639, 636],
                                                  [661, 658],
                                                  [683, 680],
                                                  [705, 702],
                                                  [727, 724],
                                                  [749, 746],
                                                  [771, 768],
                                                  [793, 790],
                                                  [815, 812],
                                                  
                                                  #S2
                                                  [841, 838],
                                                  [863, 860],
                                                  [885, 882],
                                                  [907, 904],
                                                  [929, 926],
                                                  [951, 948],
                                                  [973, 970],
                                                  [995, 992],
                                                  [1017, 1014],
                                                  [1039, 1036],
                                                  
                                                  #S3
                                                  [1064, 1061],
                                                  [1086, 1083],
                                                  [1108, 1105],
                                                  [1130, 1127],
                                                  [1152, 1149],
                                                  [1174, 1171],
                                                  [1196, 1193],
                                                  [1218, 1215],
                                                  [1240, 1237],
                                                  [1262, 1259],
                                                  
                                                  #S4
                                                  [1287, 1284],
                                                  [1309, 1306],
                                                  [1331, 1328],
                                                  [1353, 1350],
                                                  [1375, 1372],
                                                  [1397, 1394],
                                                  [1419, 1416],
                                                  [1441, 1438],
                                                  [1463, 1460],
                                                  [1485, 1482],
                                                  
                                                  #S5
                                                  [1510, 1507],
                                                  [1532, 1529],
                                                  [1554, 1551],
                                                  [1576, 1573],
                                                  [1598, 1595],
                                                  [1620, 1617],
                                                  [1642, 1639],
                                                  [1664, 1661],
                                                  [1686, 1683],
                                                  [1708, 1705],
                                                  
                                                  #S6
                                                  [1733, 1730],
                                                  [1755, 1752],
                                                  [1777, 1774],
                                                  [1799, 1796],
                                                  [1821, 1818],
                                                  [1843, 1840],
                                                  [1865, 1862],
                                                  [1887, 1884],
                                                  [1909, 1906],
                                                  [1931, 1928],
                                                  
                                                  #S7
                                                  [1956, 1953],
                                                  [1978, 1975],
                                                  [2000, 1997],
                                                  [2022, 2019],
                                                  [2044, 2041],
                                                  [2066, 2063],
                                                  [2088, 2085],
                                                  [2110, 2107],
                                                  [2132, 2129],
                                                  [2154, 2151],
                                                  
                                                  #S8
                                                  [2179, 2176],
                                                  [2201, 2198],
                                                  [2223, 2220],
                                                  [2245, 2242],
                                                  [2267, 2264],
                                                  [2289, 2286],
                                                  [2311, 2308],
                                                  [2333, 2330],
                                                  [2355, 2352],
                                                  [2377, 2374],
                                                  
                                                  #S9
                                                  [2408, 2405],
                                                  [2430, 2427],
                                                  [2452, 2449],
                                                  [2474, 2471],
                                                  [2496, 2493],
                                                  [2518, 2515],
                                                  [2540, 2537],
                                                  [2562, 2559],
                                                  [2584, 2581],
                                                  [2606, 2603],
                                                  
                                                  #S10
                                                  [2631, 2628],
                                                  [2653, 2650],
                                                  [2675, 2672],
                                                  [2697, 2694],
                                                  [2719, 2716],
                                                  [2741, 2738],
                                                  [2763, 2760],
                                                  [2785, 2782],
                                                  [2807, 2804],
                                                  [2829, 2826],
                                                                
                                                   ]
                                        
                                          group_to_check = get_group_to_get(obj, datas)
                                          if not group_to_check:
                                              return
                                        
                                          #Reset data
                                          reset(obj, group_to_check)
                                        
                                        
                                        
                                          # Trigger c4d update
                                          c4d.EventAdd()
                                        
                                        
                                      if __name__ == '__main__':
                                          main()
                                      
                                      1 Reply Last reply Reply Quote 0
                                      • H
                                        Helper
                                        last edited by

                                        On 06/06/2017 at 10:27, xxxxxxxx wrote:

                                        Here is a link to the file (3-4 sec before reset occurs).

                                        https://www.dropbox.com/s/bq3wdata1sevnuo/reset OPTIMIZE test.c4d?dl=0

                                        1 Reply Last reply Reply Quote 0
                                        • H
                                          Helper
                                          last edited by

                                          On 06/06/2017 at 12:54, xxxxxxxx wrote:

                                          def get_group_to_get(obj, datas) :
                                              buffer = list()
                                              for i in xrange(len(datas)) :
                                                  if obj[c4d.ID_USERDATA, datas[i][0]]:
                                                      obj[c4d.ID_USERDATA, datas[i][0]] = False
                                                      buffer.append(datas[i][1])
                                            
                                              return buffer
                                          

                                          Take 90% of the time. Moreover everytime the code is executed twice. I dont know why (Even if I remove c4d.EventAdd())

                                          @Scotta: You gonna miss us. And I really hope you will change your decision

                                          1 Reply Last reply Reply Quote 0
                                          • H
                                            Helper
                                            last edited by

                                            On 06/06/2017 at 13:03, xxxxxxxx wrote:

                                            Weird. Maybe Niklas has some ideas?

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post