SOLVED FieldLayer GetDirty

Hello.

I am working on a plugin that utilizes a custom FieldList I create with the code below.

    cid = DescLevel(idField, CUSTOMDATATYPE_FIELDLIST, 0);
    if (!singleid || cid.IsPartOf(*singleid, NULL))
    {
        BaseContainer bc;
        bc = GetCustomDataTypeDefault(CUSTOMDATATYPE_FIELDLIST);
        bc.SetBool(DESC_FIELDLIST_NOCOLOR, TRUE);
        bc.SetBool(DESC_FIELDLIST_NODIRECTION, TRUE);
        bc.SetBool(DESC_FIELDLIST_NOROTATION, TRUE);
        
        bc.SetString(DESC_NAME, "Field"_s);
        bc.SetBool(DESC_ANIMATE, true);
        if (!description->SetParameter(cid, bc, fieldgroup))
            return TRUE;
        
    }

My issue comes in when I try to catch when one of the objects inside of the FieldList is dirty.

The code below is how I am checking the layers in the FieldList. This code is working properly on things like the Linear Field but on layers like the Time Field Layer it doesn't catch when they are dirty.

GeData data;
	UInt32 falloffDirtySum = 0;
	const DescID fieldParameterID(idFieldList);
	if (op->GetParameter(fieldParameterID, data, DESCFLAGS_GET::NONE))
	{
		CustomDataType* const customData = data.GetCustomDataType(CUSTOMDATATYPE_FIELDLIST);
		FieldList* const  fieldList = static_cast<FieldList*>(customData);
		UInt32 falloffDirtySum = 0;
		if (fieldList)
		{
			GeListHead *listHead = fieldList->GetLayersRoot();
			if (listHead)
			{
				Int32 fieldIndex = 0;
				Int32 fieldListCount = fieldList->GetCount();

				FieldLayer *layer = static_cast<FieldLayer*>(listHead->GetFirst());
				while (layer && fieldIndex < fieldListCount)
				{
					const FieldLayerLink layerLink = layer->GetLinkedObject(doc);
					BaseObject *fieldObject = static_cast<BaseObject*>(layerLink._object);
					if (fieldObject)
					{
						falloffDirtySum = falloffDirtySum + fieldObject->GetDirty(DIRTYFLAGS::CACHE | DIRTYFLAGS::DATA | DIRTYFLAGS::MATRIX);
					}
					layer = layer->GetNext();
					fieldIndex++;
				}

			}
		}
		if (falloffDirtySum != prevFalloffDirtySum)
		{
                        // Mark object as dirty
			prevFalloffDirtySum = falloffDirtySum;
		}
	}

Running my own tests I know that this code isn't working on these layers because they don't have a linked object to retrieve with GetLinkedObject() to give me something to use GetDirty() on. Using GetDirty() on the FieldLayers that don't have a linked object doesn't work either.

Is there an alternative way to check dirtiness on FieldLayers that don't have a linked object?

I've tried looking through the SDK and on the forums and none of the solutions in the posts I looked at that dealt with a similar topic worked for me.

Any help would be greatly appreciated.

John Terenece

Hi,

It looks like you are not implementing the falloff the correct way.

If you are using GetDDescription to implement your Falloff tab you should use AddFalloffToDescription.

To use it you will need to store a point to a C4D_Falloff structure that you will alloc in your Init function and Free it in your Free function.

Once you have your pointer you can use GetDirty on C4D_Falloff. (inside your CheckDirty function if you are on an objectData)

Cheers,
Manuel

Thanks for the response.

I know about using C4D_Falloff structure and that was my initial way of adding a Falloff.

For my plugin I want to include other controls for a user that are placed alongside a Fieldlist like this if possible.

Picture 4.png

Is there a way to still achieve those same kind of results without needing to utilize AddFalloffToDescription or is that the only way to catch if items in the Fieldlist are dirty?

John Terenece

@m_magalhaes are you saying that to add FieldList to your description you must ALWAYS use a C4D_Falloff and AddFalloffToDescription?

If that is the case then why is this not documented or mentioned anywhere in the fields docs? https://developers.maxon.net/docs/Cinema4DCPPSDK/html/page_manual_fieldlist.html

Doesn't AddFalloffToDescription add a Falloff tab? This is not the same use case as using fields for other purposes. Such as what John is doing.

I am adding fields to my plugins the same way as John is. This works fine for my purposes but I am not checking dirty flags, only sampling them.

Sorry John, didn't mean to jump into your thread here, but it struck me as very strange.

Hi,

Sorry i wasn't in the right track.
First, no AddFalloffToDescription isn't mandatory, it's just another way to add the field tab the way we are doing it and the way the user might expect it. But thanks for asking, after having a better look i was expecting some nice features, but nothing new in the end.

After digging down in the code, and taking as example the delay and time layer, there's no way to know if the layer is dirty or not in a better way than GetDirty() functions.

If you have a c4d_falloff and check for dirtiness, it will retrieve the fieldList and call GetDIrty on it.
So, in your case, you can directly do fieldList->GetDIrty(doc) that the same thing.

This function, for each layer, will call their respectives CheckDirty functions. In the case of the delay and the time layer, it only be dirty if the time of the document have changed.

Hope that answers the question.

Cheers,
Manuel

Thanks for the response.

I tried using fieldList->GetDirty(doc) with a time layer inside my fieldlist and the timeline active.

GetDirty(doc) doesn't seem to catch the time layer as dirty or a layer like the Linear Field when I make changes to it. The only time it seems to catch the fieldlist as dirty is when I change the number of layers by inserting new ones or removing old ones.

Is there a specific flag that needs to be set on the fieldlist when its created in order for GetDirty to function properly?

John Terenece

Hi,

In which function do you check the dirtiness of the FieldList?

Cheers,
Manuel

Inside of CheckDirty.

John Terenece

Hi,

I've overlooked one function, my apology. Something that the Falloff->GetDirty() does is to check if the BaseContainer of the gadget.
There's no way of doing it. The only workaround i found is to give the ID of your field parameters the value FIELDS.

That way even if you don't use _pFallOff->AddFalloffToDescription(description, bc, flags)) to add the description on your UI you can still check the dirtyness of the gadget.

The problem of course is that you can't have more than one field with this ID.

So, you can add the description like this:

DescID cid = DescLevel(FIELDS, CUSTOMDATATYPE_FIELDLIST, 0);
	if (!singleid || cid.IsPartOf(*singleid, NULL))
	{
		BaseContainer bc;
		bc = GetCustomDataTypeDefault(CUSTOMDATATYPE_FIELDLIST);
		bc.SetBool(DESC_FIELDLIST_NOCOLOR, TRUE);
		bc.SetBool(DESC_FIELDLIST_NODIRECTION, TRUE);
		bc.SetBool(DESC_FIELDLIST_NOROTATION, TRUE);

		bc.SetString(DESC_NAME, "Field"_s);
		bc.SetBool(DESC_ANIMATE, true);
		if (!description->SetParameter(cid, bc, ID_OBJECTPROPERTIES))
			return TRUE;

	}

Cheers,
Manuel

Thanks for the response, that seems to have solved the issue.

John Terenece