Texture Tag inside Object Plugin [SOLVED]

On 10/07/2014 at 08:19, xxxxxxxx wrote:

I am really stuck here. 
What I am looking for is a way to assign multiple materials to the same object, without making the object editable since it's a procedural object; something similar to MultiSubObject material in 3DS MAX. This should work for a generator plugin.

Bool MyTest::Init(GeListNode *node)
	BaseObject *op = (BaseObject* )node;
	BaseContainer *data = op->GetDataInstance();
	op->SetPhong(TRUE, FALSE, 1.5);  
	TextureTag *tex = TextureTag::Alloc();    // I would like this tags to be assigned to the BOX
	TextureTag *tex1 = TextureTag::Alloc();  // I would like this tags to be assigned to the SPHERE
BaseObject* MyTest::GenerateBox(BaseObject *op)
	BaseObject *box = BaseObject::Alloc(Ocube);
	return box;
BaseObject* MyTest::GenerateSphere(BaseObject *op)
	BaseObject *sphere = BaseObject::Alloc(Osphere);
	return sphere;
BaseObject* MyTest::GetVirtualObjects(BaseObject *op, HierarchyHelp *hh)
	BaseDocument *doc = hh->GetDocument(); 	
	BaseContainer *bc = op->GetDataInstance(); 
BaseObject *ret = NULL;
	Bool dirty = op->CheckCache(hh) || op->IsDirty(DIRTYFLAGS_DATA) ;
	if (!dirty) 	return op->GetCache(hh); 
	BaseObject *box = GenerateBox(op); 
	BaseObject *sphere = GenerateSphere(op); 
	ret = box; 
		op->CopyTagsTo(ret, TRUE, FALSE, FALSE, NULL);
		return ret;	
	} else return BaseObject::Alloc(Onull);

The question is, how do I show the tags tex and tex1 in the OM and have tex change the material of the box and tex1 change the material of the sphere.

Any help would be greatly appreciated.

On 10/07/2014 at 10:27, xxxxxxxx wrote:

Create a separate texture tag for each object and attach one to each.  You will need to set the tag's Material (SetMaterial()) for each.

On 10/07/2014 at 11:24, xxxxxxxx wrote:

Hi Robert,

I already did that, and it didn't work.
The only way I got to see the tags in the return object is if I inserted the tags in the init function.

Can you please elaborate your method on the actual code that I posted?

I am not too worried about the materials because I want the user to add them at their ease. The proper assignment of the tags is the problem.

On 10/07/2014 at 16:34, xxxxxxxx wrote:

You can't show them in the OM since the virtual object is not *really* in the OM either.  The virtual objects and tags will only be visible in the OM when the user makes your Generator object editable (Ctrl-C).  You can have the user place Texture tags on your Generator object. For my Greebler plugin, I use a naming convention to specify the object and any Polygon selections.  So, for instance, if you have create two objects virtually and name them, say, Sphere1 and Sphere2, you can copy those tags on the generator to the respective objects (by naming-convention or order - first tag, first object, etc.) in GetVirtualObjects() before you return with the virtual objects.

On 10/07/2014 at 22:17, xxxxxxxx wrote:

Hi Robert, this sounds like a solution.

Being a total beginner in both C4D and its SDK, I need help getting it to work. Can you please provide a code snippet on how to achieve that? Maybe on top of the code that I showed?

I would really appreciate it.

On 11/07/2014 at 07:50, xxxxxxxx wrote:

I tried this, but C4D crashes when I add the tags manually.

	BaseTag *tex = NULL; 
	if (op->GetFirstTag() != nullptr) { 
		tex = op->GetFirstTag();
		box->InsertTag(tex, NULL);
	BaseTag *tex1 = NULL;
	if (tex!=nullptr)
		if (tex->GetNext() != nullptr) 
			tex1 = tex1->GetNext();
			sphere->InsertTag(tex1, NULL);
	ret = box;

On 11/07/2014 at 10:38, xxxxxxxx wrote:

I will post some code when I get home from work - but you need to make COPIES of the tag to insert onto your virtual objects.  You can't just get the tag from one object and insert onto another (without removing from the original object that owns it).

void DuplicateTextureTags(BaseObject* generator, BaseObject* vobj)
	// Objects should already be in hierarchical setup for this method to work:
	//  box
	//	-- sphere
	// Find Texture Tags on Generator object, clone and insert on result (vobj)
	// Never assume that the tags returned will only be Texture tags.  Sometimes
	// hidden tags, such as Polygon and Point tags on Polygon objects, will exist.
	BaseTag* ttag =	NULL;
	BaseTag* tag = NULL;
	for (tag = generator->GetFirstTag(); tag; tag = tag->GetNext())
		if (!tag->IsInstanceOf(Ttexture))	continue;
		ttag = static_cast<BaseTag*>(tag->GetClone(COPYFLAGS_0, NULL));
		if (!ttag) return;
	vobj =	vobj->GetDown();
	if (!vobj)	return;
	for (tag; tag; tag = tag->GetNext())
		if (!tag->IsInstanceOf(Ttexture))	continue;
		ttag = static_cast<BaseTag*>(tag->GetClone(COPYFLAGS_0, NULL));
		if (!ttag) return;

On 11/07/2014 at 23:38, xxxxxxxx wrote:

Robert, I am really grateful for the code. It works. So a big thanks!

A follow-up question, is there a way now to assign the tags to individual polygons instead of several virtual objects? The reason I used several objects is that's it's easy to manage, but the bounding box of the generated object is only bounding the first in the hierarchy.

In my original plugin, I am only generating 1 object. It would be great to assign the tags, procedurally, based on polygon IDs, or polygon selections. For instance, in the case of the box, say polygons 0-2 will get the first tag, and polygons 3-5 will get the second tag.

If you can help me with that it would be great, but thanks anyway!

On 12/07/2014 at 11:51, xxxxxxxx wrote:

You can set PolygonSelection tags and add them to the Texture tag's "Selection" like so:

stag->SetParameter(DescID(TEXTURETAG_RESTRICTION), GeData(polygonseltag_name), DESCFLAGS_SET_0);

Give your PolygonSelection tags unique names for this to work best.  polygonseltag_name is a String.

On 12/07/2014 at 13:08, xxxxxxxx wrote:

I added a selection tag in my init function, like so:

	SelectionTag* sTag = SelectionTag::Alloc(Tpolygonselection);
	op->InsertTag(sTag, 0);
	sTag->SetName("First Selection");

1. How do I access this tag in GVO()
2. How do I assign polygons into that selection tag , without making the object editable?

The reason I added it in the init function is that if I add it in GVO() it gets added over and over whenever I make a parameter change.

Is this the right way to add it?

On 12/07/2014 at 16:26, xxxxxxxx wrote:

In my case, I am creating the tag in GVO() from user desired selections on procedurally created polygon objects.  For your method, you can either retain pointers to the tags in your generator class or store some BaseLinks to retain links to them in the generator class (resource).

You are going to have to know which polygons (by index) to select in the BaseSelect.  Since my polygon objects are created procedurally, I set particular selections when the objects are being constructed.

On 12/07/2014 at 21:04, xxxxxxxx wrote:

And it WORKS!

Thanks a lot for you help and patience Robert.

One last question, is there a way to have the bounding box accommodate both objects if I add them in a hierarchy in GVO(). The way it happens now is the bounding box is around the first one and ignore the child.

On 13/07/2014 at 15:07, xxxxxxxx wrote:

I don't think so.  Even with "Sel: Bounding Box" with "Include Children" for the display options, the hierarchy shows the bb of each individual object and not an aggregate.  In this case, you may need to diy by adding a Draw() method to your generator.