Asset Types

Create and load assets for a wide range of content types exposed by the Asset Browser.

Overview

The Asset API can handle assets wrapping multiple types of content. Assets for known content types have specialized handling behaviours for their asset content, as for example generating preview images and loading the asset content into Cinema 4D when the asset is dragged or double-clicked. The data stored with an asset consists of two parts: The primary data, the actual content as for example an image file, and the secondary data, the metadata which describe that content. An asset description is the container which holds the metadata describing an asset, while the various forms of asset type implementations provide an interface for the primary data of the asset.

The most tangible forms of assets wrap fundamental content as scenes, objects, materials, files, node templates, and presets. But also other forms of data are represented by assets as for example categories, keywords. From an Asset API perspective there are three asset types which cover the vast majority of asset content: File, node template, and preset assets. File assets wrap most of the content delivered with the Asset Browser, ranging from scenes over objects, materials, and textures to arbitrary files. Node templates are a part of the Nodes API and represent nodes or node groups that can be part of a node graph, as for example Scene and Material Nodes. Preset assets are a specialized form of asset type that wrap a specific data type and are often also associated with a special GUI which handles loading and saving assets. Examples for such preset assets are spline and gradient presets, which both wrap the corresponding spline and gradient data types and GUIs.

Fig I: The SDK asset database delivers tangibly texture, material, object, scene, and node assets. Internally all these assets are represented by file type assets except for the two node template assets named 'Material Node ...' and 'Scene Node ...' which are represented as node template assets. Delivered are also category assets, as for example the 'SDK' category and keyword assets, as for example the 'SDK' keyword. All these various forms of assets are being represented by asset types and sub-types.

Restrictions

With the built-in asset types it is currently not possible to create an asset that wraps only a BaseTag or BaseShader. Because the former requires a BaseObject instance and the latter a BaseMaterial instance to be stored in a document. But due to the collection of asset dependencies, it is possible to store a BaseObject with its tags or a BaseMaterial with its shaders as a single asset.

Technical Overview

The implementation of all asset types is split into two parts: The implementation of an asset interface which inherits from AssetInterface and implements the functionalities that apply to singular asset of that type, as for example accessing the metadata of the specific asset. And the implementation of an asset type interface which inherits from AssetTypeInterface and implements the functionalities that apply to all assets of that type. All asset type implementations are exposed by the namespace AssetTypes which is often used to specify an asset type in operations which require an asset type to be passed.

From an asset description the corresponding asset interface can be accessed with AssetDescriptionInterface::Load, returning a reference to the base AssetInterface for that asset description and the asset description of an asset interface can be accessed with the method AssetInterface::GetDescription. On the rare occasions where a type specific asset interface for an asset description is required, the base interface must be cast with maxon::Cast into the type specific asset interface.

AssetInterface is derived from the base interface ObjectInterface, allowing assets to be instantiated as any maxon API object with its Create method, returning a reference to a newly created asset interface. But this from of asset instantiation is usually only applied to the less complex asset types, as for example keyword and category assets, where manually setting up the data and metadata of that asset is trivial. More complex asset types are instantiated with convenience functions which hide the asset interfaces away and expose directly the asset descriptions for the newly created assets. These convenience functions are primarily being provided by the interface AssetCreationInterface; offering static functions to create assets for objects, materials, scenes, textures, videos, files, and presets, as well as for loading them back. Node template assets, i.e., assets that wrap a graph node, do not have their own asset interface in the Asset API and are instead represented by NodeTemplateInterface, a member of the Nodes API, and their node template identifier is also used as their asset identifier. Node template assets must be created with NodesGraphModelInterface::MoveToAsset and loaded back by inserting the template with NodesGraphModelInterface::AddChild into a graph.

Assets of type AssetTypes::File are special in that they can have a subtype. The subtype is expressed in the metadata of the asset and can also be set with the function SubTypeAssetInterface::SetSubType. A file asset which wraps a subset of an object-hierarchy of a scene is for example of subtype maxon::ASSETMETADATA::SubType_ENUM_Object and an image file asset of subtype maxon::ASSETMETADATA::SubType_ENUM_MediaImage.

Fig II: A simplified overview of the asset type model. Assets are accessed through asset repositories which yield asset descriptions as the central interface to interact with assets. An asset description contains the metadata for an asset and can load the corresponding asset interface for the asset description. All asset types are implemented as an asset interface and an asset type interface, where the former represents a singular asset and the latter the procedures applicable to all instances of that asset type. Both the asset interface and asset type interface have access to each other. Preset assets have their own base interfaces which extend the base asset and base asset type interfaces. Implemented are these interfaces then by the specific asset types exposed by the Asset API.

Related Topics

Articles Asset API Provide content as reusable assets served with the Cinema 4D Asset Browser.
Implementing Preset Assets Implement a custom preset asset type wrapping a custom data type to be exposed by the Asset Browser.
Entity Creation

Explains the managed memory environment of the maxon API with interfaces and references.

Important API Entities AssetTypes Contains the declarations of asset types.
AssetCreationInterface Provides static convenience functions to create and load assets for materials, objects, scenes, files, and presets.
AssetDescriptionInterface Represents an asset over its metadata in an asset repository.
AssetInterface Provides the base implementation for the functionalities of a singular asset.
AssetTypeInterface Provides the base implementation for the functionalities applicable to all assets of a specific type.
BasePresetAssetInterface Provides the base implementation for the functionalities of a singular preset asset.
BasePresetAssetTypeInterface Provides the base implementation for the functionalities applicable to all preset assets of a specific type.
FileAssetInterface Represents a file asset, the most common from of asset type, wrapping a wide range of content.
NodeTemplateInterface Represents both a node and asset type which can be loaded into a nodes graph and inserted into an asset database.
CategoryAssetInterface Represents an Asset Browser category as an asset.
KeywordAssetInterface Represents an Asset Browser keyword as an asset.
SmartSearchAssetInterface Represents an Asset Browser smart search preset as an asset.
StoreAssetStruct Provides a helper structure that is used to store assets in asset repositories.
DndAsset

Provides a helper structure that is used in asset drag and drop operations.

SDK Plugins Asset API Examples

Showcases basic interactions with the Asset API to modify asset databases and their content.

Examples Create Object Assets Store a BaseObject as an asset.
Create Material Assets Store a BaseMaterial as an asset.
Create Scene Assets Store a BaseDocument as an asset.
Create Media Assets Store an image or movie as a media asset.
Create File Assets Store an arbitrary file as an asset.
Create Node Template Assets Store scene or material nodes of a node graph as assets.
Create Category Assets Create a category in which other assets can be placed.
Create Keyword Assets Create a keyword with which other assets can be described.
Link Media Assets Reference a media asset in a material.
Load Assets Load assets of any type back into the active document.
Load File Assets Manually Load file assets wrapping objects, materials, scenes or other file types manually back into Cinema 4D.
Load Node Template Assets Manually Load a node template manually back into a node graph.

Examples

The examples shown here are all related to the "Asset Types" category in the Asset API Examples plugin. With the plugin you can run these examples to see their output. Each example shown here has a link bar at its bottom, linking to the code on GitHub, as well as to a calling context on GitHub. A calling context is a function which showcases how to gather the required inputs for that specific example and is targeted at users who want to know how to carry out a specific task in more detail. The context link is named "How to call this example ...".

Create Object Assets

Stores a BaseObject as an asset.

The object is being stored with all 'connected' elements like child objects, tags, materials and shaders. Uses the convenience function AssetCreationInterface::CreateObjectAsset to simplify the process.

const maxon::AssetRepositoryRef& repository, BaseObject* obj, const maxon::Id& category)
{
BaseDocument* doc = obj->GetDocument();
if (doc == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Object without attached document."_s);
// Create the qualifying data for the asset, the actual AssetMetaData will be left empty here.
maxon::String assetName = FormatString("C++ SDK - Object Asset Example (@)", obj->GetName());
maxon::AssetMetaData metadata;
maxon::String assetVersion = "1.0"_s;
// StoreAssetStruct bundles up a category id, a lookup and a storage repository for an asset.
// which is then stored with the convenience function CreateObjectAsset().
maxon::StoreAssetStruct storeAsset{ category, repository, repository };
maxon::AssetDescription description = maxon::AssetCreationInterface::CreateObjectAsset(
obj, doc, storeAsset, assetId, assetName, assetVersion, metadata, true) iferr_return;
ApplicationOutput("Created object asset with the id: '@'", description.GetId());
return description;
}
Definition: lib_net.h:547
Definition: c4d_basedocument.h:498
Definition: c4d_baseobject.h:225
Definition: c4d_string.h:39
static MAXON_METHOD Result< AssetDescription > CreateObjectAsset(BaseObject *op, BaseDocument *activeDoc, const StoreAssetStruct &storeAssetStruct, const Id &assetId, const String &assetName, const String &assetVersion, const AssetMetaData &copyMetaData, Bool addAssetsIfNotInThisRepository)
static MAXON_METHOD Result< Id > MakeUuid(const Char *prefix, Bool compact)
Definition: apibaseid.h:253
Definition: resultbase.h:766
PyObject * obj
Definition: complexobject.h:60
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:67
#define ApplicationOutput(formatString,...)
Definition: debugdiagnostics.h:210
#define FormatString(...)
Definition: string.h:2100
C
Quality C.
Definition: macros.h:3
The maxon namespace contains all declarations of the MAXON API.
Definition: autoweight.h:14
const char * doc
Definition: pyerrors.h:226
#define iferr_scope
Definition: resultbase.h:1384
#define iferr_return
Definition: resultbase.h:1519

Create Material Assets

Stores a BaseMaterial as an asset.

The material is being stored with all 'connected' shaders. Uses the convenience function AssetCreationInterface::CreateMaterialAsset to simplify the process.

const maxon::AssetRepositoryRef& repository, BaseMaterial* mat, const maxon::Id& category)
{
if (doc == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Material without attached document."_s);
// Create the qualifying data for the asset, the actual AssetMetaData will be left empty here.
maxon::String assetName = FormatString("C++ SDK - Material Asset Example (@)", mat->GetName());
maxon::AssetMetaData metadata;
maxon::String assetVersion = "1.0"_s;
// StoreAssetStruct bundles up a category id, a lookup and a storage repository for an asset.
// which is then stored with the convenience function CreateMaterialAsset().
maxon::StoreAssetStruct storeAsset{ category, repository, repository };
maxon::AssetDescription description = maxon::AssetCreationInterface::CreateMaterialAsset(
doc, mat, storeAsset, assetId, assetName, assetVersion, metadata, true) iferr_return;
ApplicationOutput("Created material asset with the id: '@'", description.GetId());
return description;
}
Definition: c4d_basematerial.h:28
BaseDocument * GetDocument()
Definition: c4d_baselist.h:1978
Definition: c4d_basematerial.h:241
static MAXON_METHOD Result< AssetDescription > CreateMaterialAsset(BaseDocument *activeDoc, BaseMaterial *mat, const StoreAssetStruct &storeAssetStruct, const Id &assetId, const String &assetName, const String &assetVersion, const AssetMetaData &copyMetaData, Bool addAssetsIfNotInThisRepository)

Create Scene Assets

Stores a BaseDocument as an asset.

The scene is being stored with all its dependencies as objects, materials, shaders, or textures. Uses the convenience function AssetCreationInterface::CreateSceneAsset to simplify the process.

const maxon::AssetRepositoryRef& repository, BaseDocument* doc, const maxon::Id& category)
{
// Create the qualifying data for the asset, the actual AssetMetaData will be left empty here.
maxon::String assetName = FormatString(
"C++ SDK - Scene Asset Example (@)", doc->GetDocumentName());
maxon::AssetMetaData metadata;
maxon::String assetVersion = "1.0"_s;
// StoreAssetStruct bundles up a category id, a lookup and a storage repository for an asset.
// which is then stored with the convenience function CreateSceneAsset().
maxon::StoreAssetStruct storeAsset{ category, repository, repository };
maxon::AssetDescription description = maxon::AssetCreationInterface::CreateSceneAsset(
doc, storeAsset, assetId, assetName, assetVersion, metadata, true) iferr_return;
ApplicationOutput("Created scene asset with the id: '@'", description.GetId());
return description;
}
static MAXON_METHOD Result< AssetDescription > CreateSceneAsset(BaseDocument *activeDoc, const StoreAssetStruct &storeAssetStruct, const Id &assetId, const String &assetName, const String &assetVersion, const AssetMetaData &copyMetaData, Bool addAssetsIfNotInThisRepository)

Create Media Assets

Stores an image or video file as a media asset.

Other than arbitrary file assets, media assets will have a preview thumbnail reflecting the specific content of the asset and open in the picture viewer when invoked in the Asset Browser. Uses the convenience function AssetCreationInterface::SaveTextureAsset to simplify the process.

const maxon::AssetRepositoryRef& repository, const maxon::Url& url, const maxon::Id& category)
{
// Raise an error when the url does not point to a file.
if (url.IoDetect() != maxon::IODETECT::FILE)
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION, "Not a file url."_s);
// StoreAssetStruct bundles up a category id, a lookup and a storage repository for an asset.
maxon::StoreAssetStruct storeAsset{ category, repository, repository };
// Store the media file asset with its specific convenience function.
maxon::String assetName = url.GetName();
url, assetName, storeAsset, {}, false) iferr_return;
ApplicationOutput("Created media asset with the id: '@'", result.first.GetId());
return result.first;
}
static MAXON_METHOD Result< Tuple< AssetDescription, Bool > > SaveTextureAsset(const Url &imageUrl, const String &assetName, const StoreAssetStruct &storeAssetStruct, const HashSet< AssetDependencyStruct > &dependencies, Bool addAssetsIfNotInThisRepository)
Allows to pass several arguments into asset creation functions.
Definition: base_preset_asset.h:20
Definition: string.h:1235
Definition: tuple.h:611
Definition: url.h:952
PyObject PyObject * result
Definition: abstract.h:43
@ FILE
Url is a file.

Create File Assets

Stores an arbitrary file as an asset.

Many forms of assets as scenes, objects, materials and textures are file type assets which are distinguished only by their asset subtype. File type assets can also have the empty id as their subtype, allowing them to wrap around arbitrary file types as for example a PDF or Word file. File assets of unsupported subtype lack the special handling of a supported subtype asset as for example preview images or loading them when double clicked. File assets should always be stored under the correct subtype, and only assets for unsupported file types should be stored as plain file assets. Uses the convenience function SaveMemFileAsAssetWithCopyAsset which will make a copy of the file to be stored as an asset in the asset database.

maxon::Result<maxon::AssetDescription> CreateArbitraryFileAsset(
const maxon::AssetRepositoryRef& repository, const maxon::Url& url, const maxon::Id& category)
{
// Raise an error when the url does not point to a file.
if (url.IoDetect() != maxon::IODETECT::FILE)
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION, "Not a file url."_s);
// StoreAssetStruct bundles up a category id, a lookup and a storage repository for an asset.
maxon::StoreAssetStruct storeAsset{ category, repository, repository };
// Store the file as an file asset with an empty id for the subtype, resulting in a 'plain'
// file asset.
maxon::String assetName = url.GetName();
maxon::InternedId subType {};
url, storeAsset, subType, {}, assetName, false) iferr_return;
// When the asset was created successfully, set its category.
if (result.first && result.second)
{
}
ApplicationOutput("Created file asset with the id: '@'", result.first.GetId());
return result.first;
}
static MAXON_METHOD Result< Tuple< AssetDescription, Bool > > SaveMemFileAsAssetWithCopyAsset(const Url &depResultUrl, const StoreAssetStruct &storeAssetStruct, const InternedId &subType, const HashSet< AssetDependencyStruct > &dependencies, const String &assetName, Bool addAssetsIfNotInThisRepository)
static MAXON_METHOD Result< void > SetAssetCategory(const AssetDescription &asset, const Id &category)
Definition: datatypelib.h:31

Create Node Template Assets

Transforms the active selection of nodes in a node graph into an asset.

The selected nodes will be moved into a group node, then an asset for that group node will be created, and finally that group node in the graph will be replaced with the asset node. The operation will maintain wires established to nodes outside of the selection.

const maxon::AssetRepositoryRef& repository, const maxon::nodes::NodesGraphModelRef& graph,
const maxon::String& name, const maxon::Id& category)
{
// Get all selected true nodes in the graph.
if (selectedNodes.GetCount() < 1)
return maxon::IllegalArgumentError(
MAXON_SOURCE_LOCATION, "Please select nodes in the graph."_s);
// Begin a graph transaction, group the selected nodes and name the new group node.
maxon::GraphTransaction transaction = graph.BeginTransaction() iferr_return;
maxon::GraphNode groupNode = graph.MoveToGroup(
groupNode.SetValue(maxon::NODE::BASE::NAME, name) iferr_return;
// Store the group node as an asset and replace that group node by its asset and commit.
maxon::AssetDescription assetDescription;
assetDescription = graph.MoveToAsset(groupNode, repository, assetId, {}) iferr_return;
transaction.Commit() iferr_return;
// Set the name and category of the asset.
maxon::LanguageRef language = maxon::Resource::GetCurrentLanguage();
assetDescription.StoreMetaString(maxon::OBJECT::BASE::NAME, name, language) iferr_return;
if (!category.IsEmpty())
{
}
ApplicationOutput("Created node template asset with the id: '@'", assetDescription.GetId());
return assetDescription;
}
const char const char * name
Definition: abstract.h:195
Definition: basearray.h:412
const Block< const T > & ToBlock() const
Definition: basearray.h:465
MAXON_ATTRIBUTE_FORCE_INLINE Int GetCount() const
Definition: basearray.h:573
static MAXON_METHOD Result< void > GetSelectedNodes(const GraphModelRef &graphModel, NODE_KIND kind, const ValueReceiver< const GraphNode & > &callback)
Result< Bool > SetValue(const InternedId &attr, ForwardingDataPtr &&value, Bool checkAndInvalidate=true) const
Definition: graph.h:1698
Definition: graph.h:1950
Definition: graph.h:979
Result< void > Commit(const DataDictionary &userData=GetPtrSizedZeroRef< DataDictionary >(), Bool validate=true)
constexpr Bool IsEmpty() const
Definition: apibaseid.h:139
static MAXON_METHOD LanguageRef GetCurrentLanguage()
Definition: nodesystem.h:835
@ NODE
Indicates that the g-node is a true node.

Create Category Assets

Creates a category asset.

Asset categories are the folder structure visible in the Asset Browser that group other assets. Each of these categories is an asset itself and each asset, including category assets themselves, can reference exactly one category asset as its parent category.

const maxon::AssetRepositoryRef& repository, const maxon::String& name,
const maxon::Id& category)
{
if (name.IsEmpty())
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION, "Invalid category name."_s);
// Create and store a new category asset.
maxon::CategoryAsset categoryAsset = maxon::CategoryAssetInterface::Create() iferr_return;
maxon::Id categoryId = maxon::AssetInterface::MakeUuid("category", false) iferr_return;
maxon::AssetDescription assetDescription = repository.StoreAsset(
categoryId, categoryAsset) iferr_return;
// Set the category name.
maxon::LanguageRef language = maxon::Resource::GetCurrentLanguage();
assetDescription.StoreMetaString(maxon::OBJECT::BASE::NAME, name, language) iferr_return;
// Set the category of the asset when the category is not the empty id.
if (!category.IsEmpty())
{
}
ApplicationOutput("Created category asset with the id: '@'", assetDescription.GetId());
return assetDescription;
}
static MAXON_METHOD Result< CategoryAsset > Create()
OBJECT
Object mode.
Definition: lib_activeobjectmanager.h:2
#define NAME
Definition: token.h:14

Create Keyword Assets

Creates a keyword asset.

Asset keywords are used by the Asset Browser to group assets in addition to categories. Each keyword is an asset itself which can be referenced with its asset id by other assets as one of their multiple keywords.

const maxon::AssetRepositoryRef& repository, const maxon::String& name, const maxon::Id& category)
{
if (name.IsEmpty())
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION, "Invalid keyword name."_s);
// Create and store a new keyword asset.
maxon::KeywordAsset keywordAsset = maxon::KeywordAssetInterface::Create() iferr_return;
maxon::Id categoryId = maxon::AssetInterface::MakeUuid("keyword", false) iferr_return;
maxon::AssetDescription assetDescription = repository.StoreAsset(
categoryId, keywordAsset) iferr_return;
// Set the keyword name.
maxon::LanguageRef language = maxon::Resource::GetCurrentLanguage();
assetDescription.StoreMetaString(maxon::OBJECT::BASE::NAME, name, language) iferr_return;
// Set the category of the asset when the category is not the empty id.
if (!category.IsEmpty())
{
}
ApplicationOutput("Created keyword asset with the id: '@'", assetDescription.GetId());
return assetDescription;
}
#define keyword(a0, a1, a2, a3, a4, a5, a6)
Definition: Python-ast.h:677
static MAXON_METHOD Result< KeywordAsset > Create()

Link Media Assets

Loads the passed media assets as materials into the passed document.

Loads image and movie assets into a document as textures in the color channel of a material and ensures that the passed assets are indeed of asset type File and matching subtype. The major insight of this example is that the Url of a media asset can be used directly to access its content.

maxon::Result<void> LinkMediaAssets(
{
// Check for being on the main thread as this example will attempt to modify the passed document
// and also invokes EventAdd(). Due to threading restrictions the loading in of assets must only
// be done on the main thread, regardless of whether the document is loaded or not.
return maxon::UnexpectedError(
MAXON_SOURCE_LOCATION, "Example must be run on the main thread."_s);
// The file asset subtypes that form media assets.
mediaSubtypes.Append(maxon::ASSETMETADATA::SubType_ENUM_MediaImage) iferr_return;
mediaSubtypes.Append(maxon::ASSETMETADATA::SubType_ENUM_MediaMovie) iferr_return;
// Load the media assets as textures into newly created materials in the document.
maxon::Int insertedMaterials = 0;
for (maxon::AssetDescription asset : assetCollection)
{
// This is a non file type asset or a file type asst that is not of subtype media.
if (asset.GetTypeId() != maxon::AssetTypes::File.GetId())
continue;
maxon::Id subTypeId = asset.GetMetaData().Get(
maxon::ASSETMETADATA::SubType, maxon::Id()) iferr_return;
if (!mediaSubtypes.Contains(subTypeId))
continue;
// Create a new material and bitmap shader and set them up.
if (material == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION, "Could not allocate material."_s);
if (shader == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION, "Could not allocate shader."_s);
material->InsertShader(shader);
return maxon::IllegalStateError(MAXON_SOURCE_LOCATION, "Could not link shader."_s);
// Get the asset url and check if it is empty.
if (url.IsEmpty())
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION, "Url of asset is empty."_s);
const Filename file = MaxonConvert(url);
// Set the asset url as the filename parameter of the bitmap shader.
if (!shader->SetParameter(DescID(BITMAPSHADER_FILENAME), file, DESCFLAGS_SET::NONE))
return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION, "Could not set texture file."_s);
// Name the material after the asset and insert it into the document.
maxon::String assetName = asset.GetMetaString(
maxon::OBJECT::BASE::NAME, maxon::Resource::GetCurrentLanguage()) iferr_return;
material->SetName(FormatString("C++ SDK Media Asset Material (@)", assetName));
doc->InsertMaterial(material);
insertedMaterials++;
}
"Created @ materials for @ passed assets.", insertedMaterials, assetCollection.GetCount());
return maxon::OK;
}
NONE
The command asset state is not defined.
Definition: asset_command.h:0
maxon::Url MaxonConvert(const Filename &fn, MAXONCONVERTMODE convertMode)
void EventAdd(EVENT eventflag=EVENT::NONE)
Bool GeIsMainThread()
void InsertShader(BaseShader *shader, BaseShader *pred=nullptr)
Definition: c4d_baselist.h:2591
static BaseMaterial * Alloc(Int32 type)
Definition: c4d_basechannel.h:36
static BaseShader * Alloc(Int32 type)
Bool SetParameter(const DescID &id, const GeData &t_data, DESCFLAGS_SET flags)
Definition: lib_description.h:330
Manages file and path names.
Definition: c4d_file.h:94
static MAXON_METHOD Result< Url > GetAssetUrl(const AssetDescription &asset, Bool isLatest)
Bool Contains(typename ByValueParam< T >::type value) const
Definition: hashmap.h:3053
const Id & Get() const
Definition: apibaseid.h:185
MAXON_ATTRIBUTE_FORCE_INLINE ResultRef< const VALUETYPE > Append(typename ByValueParam< VALUETYPE >::type v)
Definition: collection.h:1051
for(i=0;i< length;i++)
Definition: unicodeobject.h:61
OK
Ok.
Definition: ge_prepass.h:0
Int64 Int
signed 32/64 bit int, size depends on the platform
Definition: apibase.h:188
DESCFLAGS_SET
Definition: ge_prepass.h:3359
#define Mmaterial
Standard material.
Definition: ge_prepass.h:998
Int GetCount(const ITERABLE &iterable)
Definition: collection.h:37
#define Xbitmap
Bitmap.
Definition: ge_prepass.h:1304
@ MATERIAL_COLOR_SHADER
Definition: mmaterial.h:294
const char const char const char * file
Definition: object.h:439
@ BITMAPSHADER_FILENAME
Definition: xbitmap.h:6

Load Assets

Loads any asset type back into the active document.

Uses the convenience function LoadAssets() which can load all asset types but is bound to the active document. The approach shown here will open progress popup dialogs when an asset must be downloaded.

{
// Get the user preferences repository.
maxon::AssetRepositoryRef lookupRepo = maxon::AssetInterface::GetUserPrefsRepository();
if (!lookupRepo)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Could not retrieve user repository."_s);
// AssetManagerInterface::LoadAssets() can handle loading multiple assets at once. The assets to
// be loaded are referenced by a key value pair, where the key references the asset id to load
// and the string an optional qualifier as for example "mul" when instantiating an arithmetic
// Scene Nodes node.
for (maxon::AssetDescription assetDescription : assetCollection)
{
assetToLoad.Insert(assetDescription.GetId(), ""_s) iferr_return;
}
// Load all assets. This might invoke progress bar popup dialog when an asset must be downloaded.
ApplicationOutput("Loaded @ assets.", assetCollection.GetCount());
return maxon::OK;
}
static MAXON_METHOD const UpdatableAssetRepositoryRef & GetUserPrefsRepository()
static MAXON_METHOD Result< Bool > LoadAssets(const AssetRepositoryRef &searchRepository, const HashMap< Id, String > &selectionAndFilterString, const GraphModelPresenterRef &presenter=GetZeroRef< GraphModelPresenterRef >(), const nodes::NodesGraphModelRef &graphModelRef=GetZeroRef< nodes::NodesGraphModelRef >())
Definition: hashmap.h:1119
ResultRef< Entry > Insert(KEY &&key, const V &value, Bool &created=BoolLValue())
Definition: hashmap.h:1611
return OK
Definition: apibase.h:2690

Load File Assets Manually

Loads a file asset wrapping objects, materials, scenes or other file types manually back into Cinema 4D.

Other than with the convenience function LoadAssets() this approach can also load into a document which is not the active document.

maxon::Result<void> LoadFileAssetsManually(
{
// Check for being on the main thread as this example will attempt to modify the passed document
// and also invokes EventAdd(). Due to threading restrictions the loading in of assets must only
// be done on the main thread, regardless of whether the document is loaded or not.
return maxon::UnexpectedError(
MAXON_SOURCE_LOCATION, "Example must be run on the main thread."_s);
maxon::Int32 loadedAssets = 0;
for (maxon::AssetDescription asset : assetCollection)
{
// Get the asset name and url, check the empty url and if the asset is of asset type file.
const maxon::String assetName = asset.GetMetaString(
maxon::OBJECT::BASE::NAME, maxon::Resource::GetCurrentLanguage()) iferr_return;
if (url.IsEmpty())
continue;
if (asset.GetTypeId() != maxon::AssetTypes::File.GetId())
continue;
// When the asset resides in ramdisk, check if it must be downloaded into cache. This manual
// caching is not required technically, as Cinema 4D will do it on its own when the asset is
// being accessed. But the approach shown here can be used to push download times to a more
// convenient point of time.
if (url.GetScheme() == maxon::URLSCHEME_RAMDISK)
{
// There is no cache for the asset yet, so the asset should be cached.
if (checkResult.GetSecond().IsEmpty())
{
[&assetName](Int64 current, Int64 total) -> maxon::Result<void>
{
// Display the download progress in the status bar of Cinema 4D.
maxon::Float progress = Clamp01(Float(current) / Float(total)) * 100.;
StatusSetText(FormatString("Downloading asset '@': @{.1}%", assetName, progress));
return maxon::OK;
}
}
// The actual loading part of this example, the content of the file asset is located at its
// url, and it depends on the file asset subtype how to handle that file.
// Get the asset subtype.
const maxon::Id subTypeId = asset.GetMetaData().Get(
maxon::ASSETMETADATA::SubType, maxon::Id()) iferr_return;
// Merge material and object assets with the active document, as that is usually what users
// want to do with these asset types, "import" them into an active scene, ...
if ((subTypeId == maxon::ASSETMETADATA::SubType_ENUM_Material.GetId()) ||
(subTypeId == maxon::ASSETMETADATA::SubType_ENUM_Object.GetId()))
{
if (MergeDocument(doc, MaxonConvert(url), flags, nullptr, nullptr))
loadedAssets++;
}
// and let everything else, e.g., scene and texture assets, be handled by LoadFile(). When the
// passed asset is an asset without a subtype, e.g., a PDF, LoadFile() will return false and
// nothing else will happen. So, this example will work as intended, but when it is reasonable
// to do so, it is better to check first the file extension of #url. This example covers
// everything that Cinema 4D can load, which would be a long list of file extensions, as not
// just scene files (c4d, obj, fbx, etc.), but also image and video files can be loaded by
// LoadFile(), which then will be opened in the Picture Viewer.
else
{
if (LoadFile(MaxonConvert(url), false))
loadedAssets++;
// Clear out the document path and name when the loaded asset was a scene asset, as they
// will point to the asset file otherwise. It also important to use LoadFile() to load
// scene assets and not MergeDocument() as the latter can lead to problems when the
// asset is embedded within a packed asset database (zip-file) and will also not set the
// active camera to the one defined in the scene asset.
if (subTypeId == maxon::ASSETMETADATA::SubType_ENUM_Scene.GetId())
{
BaseDocument* loadedAssetDocument = GetActiveDocument();
loadedAssetDocument->SetDocumentName(assetName);
loadedAssetDocument->SetDocumentPath(""_s);
}
}
}
"Loaded @ out of @ assets.", loadedAssets, assetCollection.GetCount());
return maxon::OK;
}
PyCompilerFlags * flags
Definition: ast.h:14
BaseDocument * GetActiveDocument()
Bool LoadFile(const Filename &name, Bool allowAsync)
Bool MergeDocument(BaseDocument *doc, const Filename &name, SCENEFILTER loadflags, BaseThread *thread, maxon::String *errorString=nullptr, const ProgressDelegate &progressDelegate=ProgressDelegate())
void StatusSetText(const maxon::String &str)
void SetDocumentPath(const Filename &path)
void SetDocumentName(const Filename &fn)
static MAXON_METHOD Result< Tuple< Bool, Url > > IsInCache(const Url &url)
static MAXON_METHOD Result< void > LoadIntoCache(const Url &url, const IoProgressDelegate &progress)
maxon::Int64 Int64
Definition: ge_sys_math.h:62
Float64 Float
Definition: apibase.h:197
int32_t Int32
32 bit signed integer datatype.
Definition: apibase.h:176
static const Id URLSCHEME_RAMDISK
Scheme identifier for virtual file systems in RAM.
Definition: url.h:845
MAXON_ATTRIBUTE_FORCE_INLINE Float32 Clamp01(Float32 a)
Clip a floating point number against the lower limit 0 and the upper limit 1. The result will be retu...
Definition: apibasemath.h:184
SCENEFILTER
Definition: ge_prepass.h:298
@ MERGESCENE
Flag to inform a plugin that this is a merge operation, i.e. the document that is inserted to is an e...
@ OBJECTS
Load/save objects.
@ MATERIALS
Load/save materials.

Load Node Template Assets Manually

Loads the passed node template identifiers manually as nodes into the passed graph.

Node template assets are special because they do not have an interface in the Asset API wrapping them. Instead, a NodeTemplate can be treated directly as asset, where the identifier of the the node template is identical to the identifier which identifies the node template within the Asset API.

maxon::Result<void> LoadNodeTemplateAssetsManually(
const maxon::AssetRepositoryRef& repository, const maxon::nodes::NodesGraphModelRef& graph,
{
// Begin a graph transaction as we will modify the graph by adding nodes.
maxon::GraphTransaction transaction = graph.BeginTransaction() iferr_return;
for (maxon::Id assetId : assetIdCollection)
{
// Get the node template for the asset id of the node template asset.
maxon::nodes::NodeTemplate nodeTemplate = maxon::nodes::NodesLib::LoadTemplate(
repository, assetId) iferr_return;
// Add an instance of that node template to the graph. When the node id is not empty, its
// uniqueness must be guaranteed by the caller, i.e., trying to add a node with the id
// maxon::Id("myId") more than once will raise an error.
maxon::GraphNode node = graph.AddChild(maxon::Id(), nodeTemplate) iferr_return;
}
// Commit the graph transaction.
transaction.Commit() iferr_return;
return maxon::OK;
}
MAXON_ATTRIBUTE_FORCE_INLINE ResultRef< T > Append(ARG &&x)
Definition: basearray.h:677
static MAXON_METHOD Result< NodeTemplate > LoadTemplate(const AssetRepositoryRef &repo, const Id &assetId)
Definition: node.h:10