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

    Cloning Materials for Generator Plugin

    SDK Help
    0
    5
    441
    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

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

      On 12/02/2004 at 17:04, xxxxxxxx wrote:

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

      ---------
      Hi,

      I'm trying to write a Generator plugin that changes some material
      properties for each object instance.

      As the material isn't cloned when the objects are cloned, I clone the
      material, and set each object-clone's TextureTag to point to its
      corresponding material-clone.

      This works. Sort of. However:

      1. The most significant problem is that C4D will often crash when I
      delete the materials in Free() :-|. I don't have any good ideas as to
      why. I'm wondering whether something like the object cloning pattern
      needs to be used (ie: first clone: use GetHierarchyClone(), subsequent
      clones: clone cloneone with GetClone()). I still don't understand
      *why* we need to make object clones in different ways.

      2. A secondary problem is that there doesn't seem to be any way to
      hide the created materials, as they must be inserted in the current
      document for the TextureTag links to be followed, and once inserted in
      the document, they are visible to the user. Is there any way to add
      the materials to the document, yet hide them?

      3. There's also a need to keep track of the original material's
      "dirty" status, which I'm not so clear on how to do.

      4. Also, when 'make editable' is invoked, the materials are of course
      deleted, leaving a bunch of TextureTags pointing to nowhere... is
      there any way to detect this?

      Any input welcome!
      Thanks.

      .angus.

      An outline of my code follows:

        
      class MyPlugin : public ObjectData  
      {  
          // ...  
          void freeMaterials();  
          std::vector<BaseObject*> materials;  
      };  
        
      void  
      MyPlugin::Free(GeListNode* /*node*/)  
      {  
          // ...  
          freeMaterials(); // this will cause CRASH  
      }  
        
      void  
      MyPlugin::freeMaterials()  
      {  
          std::vector<BaseMaterial*>::iterator it;  
          for (it = materials.begin(); it != materials.end(); ++it)  
          {  
              (*it)->Remove(); // remove material from document  
              BaseMaterial::Free(*it); // free material  
          }  
      }  
        
      BaseObject*  
      MyPlugin::GetVirtualObjects(PluginObject* op, HierarchyHelp* hh)  
      {  
          BaseDocument* bdoc = hh->GetDocument();  
          BaseObject* childone = op->GetDown();  
          // ... check dirt  
          // ... update dependence  
          if (!dirty) return op->GetCache(hh);  
        
          // root of returned tree  
          BaseObject* instroot = BaseObject::Alloc(Onull);  
          std::vector<BaseObject*> clones(numInsts);  
        
          // get first object clone  
          BaseObject* cloneone = op->GetHierarchyClone  
              (hh, childone, HCLONE_ASIS, 0, 0);  
          // ... touch dependence  
          cloneone->InsertUnderLast(instroot);  
          clones[0] = cloneone;  
        
          // make subsequent object clones  
          BaseObject* clone;  
          for (int i = 1; i < numInsts; ++i)  
          {  
              clone = cloneone->GetClone(CLONE_FLAGS, 0);  
              clone->InsertUnderLast(instroot);  
              clones _= clone;  
          }  
        
          freeMaterials();  
          materials.resize(numInsts);  
        
          // find material (eg, ignoring IsInstanceOf, casts, etc)  
          BaseMaterial* matone = childone->GetFirstTag()->GetMaterial();  
        
          // make material clones  
          BaseMaterial* mclone;  
          for (int i = 0; i < numInsts; ++i)  
          {  
              mclone = matone->GetClone(CLONE_FLAGS, 0);  
              materials _= mclone;  
              bdoc->InsertMaterial(mclone);  
          }  
        
          // update TextureTags (ignoring casts, etc)  
          for (int i = 0; i < numInsts; ++i)  
              clones _- >GetFirstTag()->SetMaterial(materials _);  
        
          // ... manipulate cloned objects and materials  
        
          return instroot;  
      }  
      
      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

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

        On 15/02/2004 at 16:32, xxxxxxxx wrote:

        First of all, this question has arisen before and unfortunately it's forbidden to add "virtual" materials in GetVirtualObjects() of a generator. As you've noticed it will lead to crashes, and the answer I got from the programmers the last time I asked about it was that this wouldn't be easy to resolve.
        So you need to insert the materials you need into the real document, even if many are needed, and there's unfortunately no way to hide them. Perhaps you could reduce the number of materials needed by making your own shader that reads parameters stored in the cloned objects?

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

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

          On 16/02/2004 at 00:24, xxxxxxxx wrote:

          Thanks for clearing up the possibility of "virtual" or hidden
          materials. I couldn't (and still can't) find previous discussion on
          the subject -- could you give me a link to the thread? And thanks for
          the suggestion to create my own shader. I need to think about that
          before I can say whether that will work for me or not...

          However, some questions remain unanswered 😞

          1. can you see anything I'm doing wrong that would cause C4D to crash
              when the materials are deleted? any hints?

          It seems that I only get a crash when freeMaterials() is called
              via Free() (ie: when the plugin is being deleted). I'm not yet
              sure what preconditions apply, as some Free's are OK.

          2. (you've answered)

          3. how do I keep track of the "dirty" status of an object not
              actually "owned" by the Generator plugin? ie: how do I track
              changes in the original material?

          4. how do I know when *not* to delete the materials I've created?
              ie: how can I tell when "make editable" has been invoked, and I
              shouldn't be deleting the materials?

          Thanks again.

          .angus.

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

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

            On 16/02/2004 at 20:23, xxxxxxxx wrote:

            0. Hm, the discussion might have been over email only. But at least I've got a definite response from the developers in the past on this.
            1. Generally it's very dangerous to do things in Free(). C4D will allocate all sorts of copies of your object, outside of your control, for example for the undo buffer. Free() should only free resource allocated by the plugin itself that noone else has seen.
            3. You should be able to use GetDirty() to get a checksum (or rather a value that's incremented when something changes). If you store this number you can check it later to see if an object has changed. (I haven't verified that this is actually implemented for materials. It should be since they are BaseList2D.)
            4. I don't think you can actually, hence the recommendation from the programmers to only create objects and let the user delete them as necessary. (Quite easy with "remove unused materials".)

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

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

              On 16/02/2004 at 21:46, xxxxxxxx wrote:

              1. Ah? Thanks.
              3. Ok. Thanks.
              4. Hm. Thanks.

              Thanks!

              .angus.

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