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



  • 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



  • 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



  • 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



  • 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



  • 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.