Solved MoGraph color tag access

Hello colleagues,
Ho can we access the color of MoGraph data for each object where Motion Graphics Color Tag [with tag->GetType() = 1018768] is assigned?

For example there is Text object or Voronoi Fracture object which have these tags for generated child objects.

Thanks in advance!

Hi @Aaron sorry I have to admit I totally overlooked your case.

So Fracture Object is a bit special in how color is handled, and this is not as an usual mograph object, where there is Modata and an array of color. Instead each part is a different PolygonObject and the color is simply the color of the object (the one from the basic tab when you select a polygon object in the attribute manager). So with that said find bellow a code to read color.

// Get the fracture object
BaseObject* obj = doc->GetFirstObject();
if (!obj && obj->GetType() == 1036557)
	return false;

// Retrieve the cache. The Cache of a fracture object consist of a null and a bunch of PolygonObject where
// each PolygonObject represents a part of the fracture.
BaseObject* rootObjCache = obj->GetCache();
if (!rootObjCache)
	return false;

BaseObject* child = rootObjCache->GetDown();
Random randomGenerator = Random();
while (child)
{
	// Read Color
	GeData data;
	child->GetParameter(DescID(ID_BASEOBJECT_COLOR), data, DESCFLAGS_GET::NONE);
	Vector color = data.GetVector();
	ApplicationOutput("@"_s, color);

	// Write Color with new random value, note that we write the cache, meaning each new re-evaluation of the Fracture object will reset these changes
	Vector randomColor = Vector(randomGenerator.Get01(), randomGenerator.Get01(), randomGenerator.Get01());
	child->SetParameter(DescLevel(ID_BASEOBJECT_COLOR), randomColor, DESCFLAGS_SET::NONE);

	// Get Next Polygon Object aka the next part from the fracture
	child = child->GetNext();
}

Cheers,
Maxime.

Hi you tagged as C++ but we do have this example in python, demonstrating two ways and the first one is by reading the modata stored in the mograph object.

Cheers,
Maxime.

Hi @m_adam Maxime,
I don't understand yet, how to use the Python example within a C++ environment. Can't find C++ functions such as this:

md = c4d.modules.mograph.GeGetMoData(op)
... 
offset = op[c4d.MG_LINEAR_OFFSET]

I have noticed that for example the Text object type has MoData->GetCount() with N elements corresponding to the number of letters. And then the cache object of Text has N children each with Motion Graphics Color Tag [tag->GetType() = 1018768].
I thought there could be a way to read this color tag somehow.

But if no then during scene traversal there is a way to inherit the array of the Text object with MoData->GetCount() > 0 and then count each descendant object with Motion Graphics Color Tag with increasing id to reference to the correct element of MoData->GetArray()

Same extraction can be done for Voronoi Fracture and other MoGraph objects with some checks.

Hi @Aaron sorry I have to admit I totally overlooked your case.

So Fracture Object is a bit special in how color is handled, and this is not as an usual mograph object, where there is Modata and an array of color. Instead each part is a different PolygonObject and the color is simply the color of the object (the one from the basic tab when you select a polygon object in the attribute manager). So with that said find bellow a code to read color.

// Get the fracture object
BaseObject* obj = doc->GetFirstObject();
if (!obj && obj->GetType() == 1036557)
	return false;

// Retrieve the cache. The Cache of a fracture object consist of a null and a bunch of PolygonObject where
// each PolygonObject represents a part of the fracture.
BaseObject* rootObjCache = obj->GetCache();
if (!rootObjCache)
	return false;

BaseObject* child = rootObjCache->GetDown();
Random randomGenerator = Random();
while (child)
{
	// Read Color
	GeData data;
	child->GetParameter(DescID(ID_BASEOBJECT_COLOR), data, DESCFLAGS_GET::NONE);
	Vector color = data.GetVector();
	ApplicationOutput("@"_s, color);

	// Write Color with new random value, note that we write the cache, meaning each new re-evaluation of the Fracture object will reset these changes
	Vector randomColor = Vector(randomGenerator.Get01(), randomGenerator.Get01(), randomGenerator.Get01());
	child->SetParameter(DescLevel(ID_BASEOBJECT_COLOR), randomColor, DESCFLAGS_SET::NONE);

	// Get Next Polygon Object aka the next part from the fracture
	child = child->GetNext();
}

Cheers,
Maxime.