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

    Get Group description children

    SDK Help
    0
    22
    11.8k
    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 01/06/2016 at 14:25, xxxxxxxx wrote:

      Hmm, the docs say the caller owns the pointed container, so I guess it must be instanced first? But that would mean the pointed container is only "filled" (though it could also mean otherwise, as I remember I used description->GetDescEntry() before with a nullptr initialisation of the temp basecontainer and it worked fine..hmmm).
      The function signature of GetNext() is kinda ugly.

        
            BaseContainer bc;  
            const BaseContainer* bcptr = &bc;  
        
            while (desc->GetNext(handle, &bcptr, id, groupid))
      

      Note: I haven't tried this code in practice. And now after writing it kind of doesn't seem right...just grabbing thoughts.

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

        On 01/06/2016 at 15:10, xxxxxxxx wrote:

        For Description::GetDescEntry() and GetNext(), the argument is const BaseContainer**.  So, &bcptr; is correct (a pointer to a pointer to a BaseContainer).

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

          On 02/06/2016 at 00:26, xxxxxxxx wrote:

          @Samir: Unfortunately the docs are wrong, C4D owns the pointed BaseContainer. I discovered the error yesterday afternoon. Will be corrected in the next release of the SDK Docs. But this is not the reason for the actual issue of this thread. Still looking into it.

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

            On 02/06/2016 at 03:32, xxxxxxxx wrote:

            @Kuro: Cheers. What I actually meant was if C4D is actually filling the pointer pointed to with an own instance pointer (allocated internally in the GetNext() function) and the user must free this one or if the pointer comes from the caller (my version). But as the docs are apparently wrong (thanks Andreas for the info), this resolves that it should be nullptr initialised. : )

            @Andreas: thx. Hmm, what is the actual issue of the code then? What is not working with the provided example?

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

              On 03/06/2016 at 02:52, xxxxxxxx wrote:

              Originally posted by xxxxxxxx

              Just wanted to let you know, that I can reproduce your issue, but haven't found the culprit, yet.

              Glad to hear. 
              Thanks for your efforts. 🙂

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

                On 03/06/2016 at 10:19, xxxxxxxx wrote:

                @mp5gosu: I'm sorry, I wasn't able to find the issue until now. Unfortunately I will be at our developer meeting, so surely won't make any progress during the next week. I'm planning to continue to work on this after my return. By experience I already know, that it will get a bit turbulent, when the team has been off for an entire week, so please ping me again, if I don't return to you within a reasonable amount of time (lets say Wednesday?). Terribly sorry!

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

                  On 03/06/2016 at 10:27, xxxxxxxx wrote:

                  Hey Andreas, no worries! I know you Maxonians are busy but dedicated people. 😉
                  Sure, I'll note you.

                  However, thanks again for having a look into this issue. 
                  It's not crucial for me right now but would make me write way less code. Also for others this would help solving some problems regarding this issue.

                  Cheers, have a nice weekend and have some fun on the DevMeet!

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

                    On 13/06/2016 at 22:50, xxxxxxxx wrote:

                    Here's your personal reminder. 😉
                    Did you find some time to sort this out yet?

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

                      On 14/06/2016 at 00:38, xxxxxxxx wrote:

                      No, I haven't yet. But I haven't forgotten either. Nevertheless thanks for the reminder. I'll continue to investigate today.

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

                        On 14/06/2016 at 05:33, xxxxxxxx wrote:

                        TL;DR but here's a class that I built for the Vray project that allows to browse all parameters in the
                        description and check the parent group. For the way I use it, it's working very good. You may use it
                        as you like. Usage is pretty straight forward:

                        vb::desc::StructureHelper structure(description);
                        for (auto const* info : structure.iter()) {
                        	if (structure.CheckGroup(info->did, THE_GROUP_ID)) {
                        		// This parameter is inside the group THE_GROUP_ID
                        		// ...
                        	}
                        }
                        

                        In case you don't want to skip the iterator part, nr_iterator is here.

                        /// Copyright(C) 2015  Niklas Rosenstein
                        /// Developed for laubLAB KG.
                        ///
                        /// Source/Library/lib_desc.h
                          
                        #pragma once
                        #include "c4d.h"
                        #include "nr/iterator.h"
                          
                        namespace vb {
                        namespace desc {
                          
                        	/**
                        	 * Structure that contains the parameter information as it is yielded by
                        	 * #Description::GetNext().
                        	 */
                        	struct ParamInfo {
                        		BaseContainer const* bc = nullptr;
                        		DescID did;
                        		DescID gid;
                        	};
                          
                        	/**
                        	 * This is a helper class for reading structural information from a node's
                        	 * #Description. For instance, it allows you to check if a parameter is inside
                        	 * a specific group.
                        	 */
                        	class StructureHelper {
                        	private:
                        		friend class Iterator;
                        		maxon::HashMap<Int32, ParamInfo> map;
                        		maxon::BaseArray<Int32> order;  // required for correct order iteration
                        	public:
                        		StructureHelper() { }
                        		StructureHelper(Description* desc) { Init(desc); }
                        		~StructureHelper() { }
                          
                        		inline Bool Init(Description* desc) {
                        			this->map.Flush();
                        			this->order.Flush();
                        			if (!desc) return false;
                        			ParamInfo param;
                        			void* handle = desc->BrowseInit();
                        			while (desc->GetNext(handle, &param.bc, param.did, param.gid)) {
                        				this->map.Put(param.did[0].id, param);
                        				this->order.Append(param.did[0].id);
                        			}
                        			desc->BrowseFree(handle);
                        			return true;
                        		}
                          
                        		/**
                        		 * Returns the #ParamInfo info structure for a specific description ID
                        		 * #did or nullptr if there is no parameter with the specified ID.
                        		 */
                        		// @{
                        		inline ParamInfo const* Get(Int32 did) const {
                        			auto* entry = this->map.FindEntry(did);
                        			if (entry) return &entry->GetValue();
                        			return nullptr;
                        		}
                          
                        		inline ParamInfo const* Get(DescID const& did) const {
                        			return this->Get(did[0].id);
                        		}
                        		// @}
                          
                        		/**
                        		 * Returns the #ParamInfo for the parent group of the specified parameter.
                        		 */
                        		inline ParamInfo const* GetParentGroup(ParamInfo const* info) const {
                        			if (!info || info->did[0].id == info->gid[0].id) return nullptr;
                        			return this->Get(info->gid);
                        		}
                          
                        		/**
                        		 * Checks if the parameter with the description ID #did is anywhere
                        		 * in the group specified by #gid and returns true in that case, false
                        		 * otherwise.
                        		 */
                        		inline Bool CheckGroup(DescID did, DescID const& gid) const {
                        			while (did != gid) {
                        				ParamInfo const* group = this->Get(did);
                        				if (!group) return false;
                        				did = group->gid;
                        			}
                        			return true;
                        		}
                          
                        		/**
                        		 * Helper to iterate over the entries in the description. This will
                        		 * happen in the same order as the iteration over the source #Description.
                        		 */
                        		class Iterator : public nr::iterator<Iterator> {
                        		private:
                        			StructureHelper const& helper;
                        			decltype(StructureHelper::order) ::ConstIterator it, itend;
                        		public:
                        			Iterator(StructureHelper const& helper) : helper(helper), it(helper.order.begin()), itend(helper.order.end()) { }
                        			Bool at_end() const { return it == itend; }
                        			ParamInfo const* operator * () const { return helper.Get(*it); }
                        			void next() { ++it; }
                        		};
                          
                        		inline Iterator iter() const { return Iterator(*this); }
                          
                        	};
                          
                        }} // namespace vb::desc
                        
                        1 Reply Last reply Reply Quote 0
                        • H
                          Helper
                          last edited by

                          On 14/06/2016 at 09:55, xxxxxxxx wrote:

                          Thanks Niklas. Storing the data into a struct seems like a reasonable approach. I'll give it a try if I find some time. 😉

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

                            On 30/06/2016 at 03:42, xxxxxxxx wrote:

                            Hey Andreas, any progress here yet? 😉

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

                              On 18/08/2016 at 09:07, xxxxxxxx wrote:

                              Hi,

                              not sure, if you are still waiting for me, here... I'm terribly sorry, but you gave me quite a hard nut and I was stupidly searching at the wrong end. And in the end it was Sebastian, who solved this.

                              Cinema 4D calls GetDDescription() quite a bunch of times. Amongst others when building the GUI and during SetParameter(). When building the GUI your code works and so you see the correct entries in the cycle box. But when calling it during SetParameter(), GetDDescription() is called in "single description mode". When in this mode, calling GetParameterI() sets the description into a special mode, with the effect that any following browse will return only one parameter. With your code this has the unfortunate effect, that you won't fill the items container. So SetParameter() thinks, there are no options and the parameter won't be set.

                              For you this means, you can either split your loop and first browse/collect the cycle box items before calling GetParameterI().
                              Or you can use a second temporary description for your browse loop.

                              AutoAlloc<Description> tempDescription;
                              tempDescription->LoadDescription(node->GetType());
                              

                              The reasons for this behavior seem to be some heavy optimization, but we need to check this with development. Then we will see, how we can document it properly.

                              Again, terribly sorry, this took so long.

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

                                On 18/08/2016 at 09:19, xxxxxxxx wrote:

                                Wow, huuuge thanks to you Andreas!
                                Also Sebastian, please buy him a beer. 😉

                                Indeed I was eagerly waiting for a response to this. And your answer is very enlightening. 
                                With this information, I'm able to circumvent this behaviour in future projects and also reduce my current code a lot!

                                Cheers!

                                :hugging:

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