Solved Loading Materials from AssetDescriptions into a Scene

Thanks for the help @ferdinand, the plugin rewrite from python is coming along nicely and I am able to fetch all AssetDescription* from the Asset API.

However reading the handbook I am unable to find a way to fetch a BaseMaterial* from the AssetDescription*. Are you able to guide me towards a solution? I need this to be able to create a Take with a specific material.

Hello @krfft,

thank you for reaching out to us. I did fork your question because it was a new question.

About your question: This part of the Asset API has unfortunately not been documented yet. Neither in form of a handbook or examples provided by us, nor in form of doc-strings provided by our developers. We plan to update the handbook soon, but what you must do in principle is use AssetCreationInterface and there the function CreateMaterialsOnDrag. Which was named a bit weirdly (at least from an SDK user point of view) and should be more interpreted as LoadMaterialAssetIntoDocument. You could technically also use the maxon::Url of a material asset to load in the asset document manually via LoadDocument, but you would then have to unpack some of the material data yourself.

I will post an example in the next days, but I do not have the time to do it today.

Cheers,
Ferdinand

MAXON SDK Specialist
developers.maxon.net

Hello @krfft,

here the promised code. It is an extension of the Search Assets example which can be found in the Asset API Handbook.

I hope this helps and cheers,
Ferdinand

The result:
1.gif

The code:

static Int32 g_max_materials = 10;
/// ------------------------------------------------------------------------------------------------
/// Loads in the first ten material assets into the active document which can be found in the user
/// prefs repository. 
///
/// I did remove most of the comment fluff here, assuming you are already familiar with the rest.
/// ------------------------------------------------------------------------------------------------
maxon::Result<void> LoadAssets()
{
  iferr_scope;

  // Get the active document and do some setup stuff to search for all materials in the user prefs
  // repository. See FindAssets() example function in the Assets API exmaples for details.
  BaseDocument* doc = GetActiveDocument();
  if (doc == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "No active document."_s);

  const maxon::AssetRepositoryRef& repository = maxon::AssetInterface::GetUserPrefsRepository();
  const maxon::AssetType assetType = maxon::AssetTypes::File();
  const maxon::Id assetFindId = {};
  const maxon::Id assetVersion = {};
  maxon::BaseArray<maxon::AssetDescription> results;

  repository.FindAssets(
    assetType, assetFindId, assetVersion, maxon::ASSET_FIND_MODE::LATEST, results) iferr_return;

  // Iterate over the results until we have found ten materials.
  maxon::Int counter = 0;
  for (maxon::AssetDescription assetDescription : results)
  {
    if (counter == g_max_materials)
      break;

    maxon::AssetMetaData metadata = assetDescription.GetMetaData();
    maxon::Id subTypeId = metadata.Get(maxon::ASSETMETADATA::SubType) iferr_return;

    // This is a material asset.
    if (subTypeId == maxon::ASSETMETADATA::SubType_ENUM_Material)
    {
      // With a valid url.
      maxon::Url url = assetDescription.GetUrl() iferr_return;
      if (url.IsEmpty())
        continue;

      // The url of the asset is in case of material assets a c4d file. So, we  merge that asset
      // document with the active document.
      ApplicationOutput("@| Type: @, Url: @", counter, subTypeId, url);
      maxon::String* error = {};
      maxon::Bool didMerge = MergeDocument(
        doc, MaxonConvert(url), SCENEFILTER::MATERIALS, nullptr, error);
      ApplicationOutput("@: Merged: @,  Error: @", counter, didMerge, error);

      if (didMerge)
        counter++;
    }
  }

  return maxon::OK;
}

MAXON SDK Specialist
developers.maxon.net