Texture Tag inside Object Plugin [SOLVED]

On 04/07/2014 at 10:05, xxxxxxxx wrote:

You assign the material to the object using a Texture tag on the object and using ttag->SetMaterial() (where ttag is a pointer to your TextureTag).  Your best option is to create the Material once (possibly on the first creation of your objects) and check for their existence thereafter (use a unique name or some other distinguishing criteria).  You could store a Link in your plugin object that stores the Material once assigned and you would only create the Material if the Link was NULL or reset the Link if the Material being used changes (if ever).  Since you will be creating the objects and texture tags everytime GVO() runs through, you will need to set the Material link and tag each time.

On 05/07/2014 at 07:33, xxxxxxxx wrote:

Thanks for the reply Robert. I found a solution for the material creation problem in this thread
Thanks Matthias!

I still have the other (bigger) problem of assigning different texture tags to the same  object.
What I mean is this:
Suppose the generator plugin creates 2 cubes. Each cube is coming from a function, say CreateCube().

In GVO(), I return CreateCube(). To add the other cube, I insert it under the first one, using InsertUnder()

This works fine. Now how do I get to assign a different texture tag to each of the cubes, so I can assign to each a different material.

A code snippet would be greatly appreciated.

On 05/07/2014 at 12:03, xxxxxxxx wrote:

If I create the texture tag in the function generating the cube, each parameter change will generate a new texture tag, and that goes on infinitely...

I am looking for a way to generate say 2 texture tags, and assign each to a different cube in a plugin that generates 2 cubes.

On 06/07/2014 at 01:32, xxxxxxxx wrote:

If I create the texture tags in MSG_MENUPREPARE, then the insertion of the tags will happen once, which is good.

I was thinking if I can use TEXTURETAG_RESTRICTION to a selection of polygons by polygon index.
For example, if the plugin is generating 2 cubes, and each cube had 6 polygons, I can tell texTag1 to affect the first 6 polygons, and texTag2 to affect the next 6 polygons.

Is there a way to do that?

Note: I cannot make the object editable because it's a procedurally animated object.

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.