Solved HandleMouseDrag for ID_GRADIENTGUI_BROWSERPRESET and ColorSwatchData::browserPresetType

If I have a lib4d that contains ID_GRADIENTGUI_BROWSERPRESET and ColorSwatchData::browserPresetType presets, how can I start a Drag and Drop event from my own GeUserArea to pass these to other parts of C4D?

I have the SDKBrowserURL to each preset contained with my own lib4d files.

I then want to call GeUserArea::HandleMouseDrag() with the appropriate DRAGTYPE and pass in the appropriate data.

Is this possible? If so, how?

I can call SDKBrowser::LoadPreset(_db_index, _browserURL, plugin_id, &bc, &data, &length) to get the data and its length. But I do not know where the data should be set in order to pass in the appropriate struct or class to HandeMouseDrag, and I do not know what the DRAGTYPE would be for this either.

Thanks!

hi,

we are not sure in witch direction you want to operate.

Is it something you are dragging from the asset browser or to the asset browser ?

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

Hi Manuel,

From my GeUserArea to anywhere in C4D. I am loading the presets from the lib4d myself. The content browser in C4D is not involved at all.

So the user will be dragging a color swatch preset from my GeUserArea to something such as such the color swatches on the color channel of a material.

What is the DRAGTYPE and data for Gradient presets and color swatch presets?

Thanks,
Kent

It looks like color swatches and gradients both take an RGBA Array like so. (Although I am not sure about where the knot value for the gradients comes from yet, perhaps it takes it from the Alpha?).

ColorAlphaArray arr;
arr.Append(maxon::ColorA(1, 0, 0, 1)) iferr_ignore(""_s);
arr.Append(maxon::ColorA(0, 1, 0, 1)) iferr_ignore(""_s);
HandleMouseDrag(msg, DRAGTYPE_RGBA_ARRAY, &arr, 0);

But how to do I extract these from a preset?

I should also point out that I am loading my lib4d by calling SDKBrowser::RegisterPresetLibrary(...)

I am then iterating over all the presets and checking the preset type to see if they are ID_GRADIENTGUI_BROWSERPRESET or ColorSwatchData::browserPresetType.

If the preset type is ColorSwatchData::browserPresetType then I would expect the following to work, but it does not.

ColorSwatchData *swatch = ColorSwatchData::Alloc(GetActiveDocument());
if (swatch)
{
	if (swatch->LoadPreset(_browserURL, false))
	{
		if (swatch->GetGroupCount() > 0)
		{
			ColorSwatchGroup *group = swatch->GetGroupAtIndex(0);
			if (group)
			{
				ColorAlphaArray arr;
				group->GetColors(arr);
				HandleMouseDrag(msg, DRAGTYPE_RGBA_ARRAY, &arr, 0);
			}
		}
	}
	ColorSwatchData::Free(swatch);
}

So instead I tried to see if I could simple cast the preset data myself, but calling it like this does not work either.

Int32 plugin_id;
BaseContainer bc;
void *data = nullptr;
Int length = 0;

//Where _db_index is the index returned from my registered preset library, and _browserURL is the SDKBrowserURL to the actual preset within the library itself.
if (SDKBrowser::LoadPreset(_db_index, _browserURL, plugin_id, &bc, &data, &length))
{
	if (plugin_id == ColorSwatchData::browserPresetType)
	{
		//Note: The data does not appear to be ColorSwatchData, I can not simply cast it as shown below
		ColorSwatchData* swatch = (ColorSwatchData*)data;
		ColorSwatchGroup *group = swatch->GetGroupAtIndex(0);
		if (group)
		{
			ColorAlphaArray arr;
			group->GetColors(arr);
			HandleMouseDrag(msg, DRAGTYPE_RGBA_ARRAY, &arr, 0);
		}
	}
}

Trying to load it as a document doesn't work either. The error message when trying to load the document from the in memory file says that the document doesn't seem to exist.

Filename readFileName("temp.doc");
readFileName.SetMemoryReadMode(data, length, true);

maxon::String err;
BaseDocument *pLoadedDoc = LoadDocument(readFileName, SCENEFILTER::NONE, nullptr, &err);
if (pLoadedDoc)
{
	ColorSwatchData *swatchDoc = ColorSwatchData::Alloc(pLoadedDoc);
	if (swatchDoc)
	{
		ColorSwatchGroup *group = swatch->GetGroupAtIndex(0);
		if (group)
		{
			ColorAlphaArray arr;
			group->GetColors(arr);
			HandleMouseDrag(msg, DRAGTYPE_RGBA_ARRAY, &arr, 0);
		}
		ColorSwatchData::Free(swatchDoc);
	}
	BaseDocument::Free(pLoadedDoc);
}

So far I have not found a solution for gradients either.

hi,

sorry for this poor answer. I cannot find why it's not working. I need more time to investigate (or ask the devs)

I hope this will help you a bit.
as you saw, for a group or a single swatch the type is DRAGTYPE_RGBA_ARRAY

The intern code is very similar to what you are doing.

This is the part of the code that call the HandleMouseDrag. (for a group)
bc886487-3bb7-4e3a-83e0-1624fc52616d-image.png

It's called from the InputEvent of the ColorSwatchesArea (which is a GeUserArea).

That could be interesting to handle the return of HandleMouseDrag

Sometime HandleMouseDrag is called with that flag HANDLEMOUSEDRAG_PRIVATEFRAME but can't figure out what's really the point of using it.

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

Thanks for looking Manuel.

The question now is really just how can I get to the data in the presets?

If that’s not possible then I will just write my own file format for color swatches and gradients and have to avoid using lib4d files for these.

Hope there is a way to use the presets though, will save me some time. Thanks.

hi,

adding the following InputEvent to our GeUserArea in the geDialog gadget example seems to work as expected. If i understood correctly the question.
If the userArea is clicked, I load the preset inside my custom library (mylib.lib4d and preset mycolors). I retrieve the color information to an array, and call the HandleMouseDrag

This Manual was helpful :
ColorSwatchGroup

Bool InputEvent(const BaseContainer& msg) override
	{
		const maxon::String urlPreset = "preset://mylib.lib4d/mycolors"_s;
		const SDKBrowserURL presetUrl = SDKBrowserURL(urlPreset);

		AutoAlloc<ColorSwatchData> colorPreset;
		if (colorPreset == nullptr)
			return false;
		ColorAlphaArray colorArray;

		if (ColorSwatchData::ValidPreset(presetUrl))
		{
			if (colorPreset->LoadPreset(presetUrl))
			{
				ColorSwatchGroup* myGroup = colorPreset->GetGroupAtIndex(0);
				myGroup->GetColors(colorArray, false);
                                // instead of returning the result of the function, one should want to handle the result correctly.
				return HandleMouseDrag(msg, DRAGTYPE_RGBA_ARRAY, &colorArray, 0);
			
			}
		}

		return true;
	}

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

Hi Manuel,

Thanks for looking into it. But this code does not work, and I think the reason is because I am registering the library myself.

SDKBrowser::RegisterPresetLibrary(...)

IE it is not in the ContentBrowser user interface at all. So the call to ColorSwatchData::ValidPreset(presetUrl) seems to fail when this is the case.

Would it be possible to get the code that extracts the data from the preset itself?

Int32 plugin_id;
BaseContainer bc;
void *data = nullptr;
Int length = 0;

//Where _db_index is the index returned from my registered preset library, and _browserURL is the SDKBrowserURL to the actual preset within the library itself.
if (SDKBrowser::LoadPreset(_db_index, _browserURL, plugin_id, &bc, &data, &length))
{
  // I now have the data. I would like to extract the information from it.
}

Again this would be for both ColorSwatch and Gradient presets.

Thanks,
Kent

hi,

I would need to define how the preset encapsulate the data itself. And than expose how the data is stored.
(that took me some time to figure that out sorry about the delay)
I will ask if we can share this information.

I will have a look at why it's not working with a registered library.

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

hi,
I was trying to reproduce the problem of loading a preset from a registered library but can't reproduce it.
I tested it with the last version maybe that's the problem.

Could you tell me witch version are you using ?
or, try this code, does it works ?

	Bool InputEvent(const BaseContainer& msg) override
	{

		// register my own lib 
		const SDKBrowserURL domain{ "preset://mycolors.lib4d"_s };
		const maxon::String libName{ "the library name"_s };
		const maxon::String presetName{ "mynewcolors"_s };
		const SDKBrowserURL presetUrl = domain + presetName;
		Filename presetLibFile{ "D:\\temp\\mycolors\\mycolors.lib4d"_s };

		const Int32 bd_index = SDKBrowser::RegisterPresetLibrary(domain, libName, presetLibFile);


		AutoAlloc<ColorSwatchData> newColorPreset;
		if (newColorPreset == nullptr)
			return false;

		ColorSwatchGroup* myGroup = newColorPreset->AddGroup();
		if (myGroup == nullptr)
			return false;
		const maxon::ColorA firstColor{ 1.0, 1.0, 1.0, 0 };
		const maxon::ColorA secondColor{ 0.4, 1.0, 1.0, 0 };
		const maxon::ColorA thirdColor{ 0.1, 0.5, 1.0, 0 };
		const maxon::ColorA fourthColor{ 0, 0, 0, 0 };

		myGroup->AddColor(firstColor);
		myGroup->AddColor(secondColor);
		myGroup->AddColor(thirdColor);
		myGroup->AddColor(fourthColor);

		if (!newColorPreset->SavePreset(presetUrl))
			return false;

		// normal way of doing it 
		AutoAlloc<ColorSwatchData> colorPreset;
		if (colorPreset == nullptr)
			return false;
		ColorAlphaArray colorArray;

		if (ColorSwatchData::ValidPreset(presetUrl))
		{
			if (colorPreset->LoadPreset(presetUrl))
			{
				ColorSwatchGroup* myColorPresetGroup = colorPreset->GetGroupAtIndex(0);
				myColorPresetGroup->GetColors(colorArray, false);
				for (auto value : colorArray)
					ApplicationOutput("color in the array @", value);

				return HandleMouseDrag(msg, DRAGTYPE_RGBA_ARRAY, &colorArray, 0);

			}
		}


		return true;
	}

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

Thanks Manuel. It looks like you are creating the preset and then using it directly all in the one go. I am loading an registering an existing library from disk and trying to access the presets within that. I will do some more investigation into it next week and let you know how I get on. Thanks again, Kent.

hi,

did you got time to look at it ?

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

Hi Manuel,

Sorry no I haven't yet. Been a busy couple of weeks. Hopefully I will have time next week to look into this again. Although due to the issues I had, and that there is still no information about how to work with gradients, I am still leaning towards ditching lib4d files and making my own custom format instead.

Will let you know next week when I have had another look into it. Thanks for following up with me.

Cheers,
Kent

Hello @kbar,

without any further questions or replies, we will consider this topic to be solved by Monday and flag it accordingly.

Thank you for your understanding,
Ferdinand

MAXON SDK Specialist
developers.maxon.net

Hi @ferdinand

This has not been solved. I could not get the data and there was no information for accessing gradient info.

I have abandoned this approach and am going to make a custom format of my own for storage.

Also in light of the depreciated Content Browser there is no point spending any more time on this issue.

Cheers,
Kent

Hello @kbar,

if you need further information, please feel free to unflag this topic. But as you know, we have a fourteen-days radio silence policy for closing topics. We understand that this can collide with workloads in a production environment, but we have to apply some form of control here. Which we feel is rather generous, since you can push back a topic almost indefinitely by simply posting in it.

Thank you for your understanding,
Ferdinand

MAXON SDK Specialist
developers.maxon.net

Hi,

my apology, i was waiting for feedback about the ColorSwatchData to dive into the gradient. I could not also talk about the Asset Browser in public.

MAXON SDK Specialist

MAXON Registered Developer

Hi,

Sorry about not having time to investigate the gradient part of your question. I was waiting for feedback about the color presets.
With the new asset browser out there's no point into investigate this question furthermore.

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer