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:
Cinema 4D Version: 8.2
Platform: Windows ; Mac OSX ;
Language(s) : C++ ;
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
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!
An outline of my code follows:
class MyPlugin : public ObjectData
freeMaterials(); // this will cause CRASH
for (it = materials.begin(); it != materials.end(); ++it)
(*it)->Remove(); // remove material from document
BaseMaterial::Free(*it); // free material
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);
// get first object clone
BaseObject* cloneone = op->GetHierarchyClone
(hh, childone, HCLONE_ASIS, 0, 0);
// ... touch dependence
clones = cloneone;
// make subsequent object clones
for (int i = 1; i < numInsts; ++i)
clone = cloneone->GetClone(CLONE_FLAGS, 0);
clones _= clone;
// find material (eg, ignoring IsInstanceOf, casts, etc)
BaseMaterial* matone = childone->GetFirstTag()->GetMaterial();
// make material clones
for (int i = 0; i < numInsts; ++i)
mclone = matone->GetClone(CLONE_FLAGS, 0);
materials _= mclone;
// update TextureTags (ignoring casts, etc)
for (int i = 0; i < numInsts; ++i)
clones _- >GetFirstTag()->SetMaterial(materials _);
// ... manipulate cloned objects and materials
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?
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?
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".)
On 16/02/2004 at 21:46, xxxxxxxx wrote:
1. Ah? Thanks.
3. Ok. Thanks.
4. Hm. Thanks.