SOLVED API for Project Asset Inspector?

Hi,

Is there an API for the project asset inspector?
Quick search on the documentation and the forum gives me nothing but I could be wrong.

Examples of usage is I want to query if a specific texture is used in a scene and if it is, what material/s is it used.

Regards,
Ben

Hello @bentraje,

Thank you for reaching out to us. As always with the Cinema 4D API, we never expose managers themselves, but the data structures they rely on. So, there is no Project Asset Inspector API, but its fundamental underlying data type AssetData is exposed in C++.

In principal, you are then meant to send a MSG_GETALLASSETS message to a node to retrieve all its assets. However, in Python this will crash Cinema 4D. You must here instead use the convenience function c4d.documents.GetAllAssetsNew. There is also a function named c4d.documents.GetAllAssets, its main difference is that it does not support Nodes API node template dependencies, so you should always use the "new" function. Find an example for its usage below.

I fixed the docs in Python, there will be a warning for MSG_GETALLASSETS in the upcoming release that it is only supported as an outgoing message. The fact that Cinema 4D can be crashed with this message should also be fixed, but we will treat this with a lower priority.

Cheers,
Ferdinand

The example scene I ran the code on:
Screenshot 2022-10-31 at 12.10.37.png

The output for the example scene, I used only (maxon) Asset API assets in this scene, i.e., stuff dragged from the Asset Browser, and therefore all filename fields hold URLs in the asset scheme. This has nothing to do with the Classic API concept of assets as embodied by the Asset Inspector, and instead is how maxon API assets are referenced internally. If you use textures on a local disk or network-drive, you will see here "normal" file scheme URLs, e.g., "c:\tex\stone\marble_01.jpg".

{'assetname': 'Untitled 1.c4d',
 'channelId': -1,
 'exists': True,
 'filename': '/Users/f_hoppe/Desktop/Untitled 1.c4d',
 'netRequestOnDemand': False,
 'nodePath': '',
 'nodeSpace': '',
 'owner': None,
 'paramId': -1}

{'assetname': 'assetdb:///Textures/Surfaces/Asphalt/asphalt_120x120.jpg',
 'channelId': 6,
 'exists': True,
 'filename': 'asset:///file_3c3a12adac26f0de~.jpg',
 'netRequestOnDemand': True,
 'nodePath': '',
 'nodeSpace': '',
 'owner': <c4d.BaseShader object called Bitmap/Bitmap with ID 5833 at 140468515064192>,
 'paramId': 1000}

{'assetname': 'assetdb:///Textures/Imperfections/si-v1_deposits_08_15cm.png',
 'channelId': -1,
 'exists': True,
 'filename': 'asset:///file_e54dfeffbe76e719~.png?name=si-v1_deposits_08_15cm.png&db=MaxonAssets.db '
             '(assets.maxon.net)&version=1.0',
 'netRequestOnDemand': False,
 'nodePath': '',
 'nodeSpace': '',
 'owner': <c4d.BaseObject object called Relief/Relief with ID 5173 at 140468515064320>,
 'paramId': 1263}

{'assetname': 'assetdb:///Textures/Surfaces/Patterns/basic018.jpg',
 'channelId': -1,
 'exists': True,
 'filename': 'asset:///file_e5e136f017243d1b~.jpg?name=basic018.jpg&db=MaxonAssets.db '
             '(assets.maxon.net)',
 'netRequestOnDemand': True,
 'nodePath': '',
 'nodeSpace': '',
 'owner': <c4d.BaseShader object called Bitmap/Bitmap with ID 5833 at 140468515064448>,
 'paramId': 1000}

{'assetname': 'assetdb:///Textures/Surfaces/Brick Wall/A019BM.TIF',
 'channelId': -1,
 'exists': True,
 'filename': 'asset:///file_e77180a827833fb4~.TIF?name=A019BM.TIF&db=MaxonAssets.db '
             '(assets.maxon.net)',
 'netRequestOnDemand': True,
 'nodePath': '',
 'nodeSpace': '',
 'owner': <c4d.BaseShader object called Bitmap/Bitmap with ID 5833 at 140468515064576>,
 'paramId': 1000}

The code:

"""Demonstrates retrieving all assets for a document in the sense of the Classic API Asset Inspector
Manager.
"""
import c4d
import typing
import pprint

doc: c4d.documents.BaseDocument # The active document.

def main() -> None:
    """
    """
    # The call is pretty straight forward, it is only a bit C-ish in that it uses an out-parameter,
    # the result will be written to #assets. See the docs for details on arguments, especially the
    # arguments #flags.
    assets: list[dict[str, typing.Any]] = []
    res: int = c4d.documents.GetAllAssetsNew(
        doc=doc,
        allowDialogs=False, 
        lastPath="", 
        flags=c4d.ASSETDATA_FLAG_0, 
        assetList=assets)

    # The whole operation failed, #assets is still the empty list.
    if res == c4d.GETALLASSETSRESULT_FAILED:
        raise RuntimeError(f"Could not gather assets for '{doc.GetDocumentPath()}'.")
    # Some of the assets in the results could not be resolved, their "exists" field will be #False.
    if res == c4d.GETALLASSETSRESULT_MISSING:
        print ("Warning: The asset data contain unresolved dependencies.")

    # Print the data.
    for item in assets:
        pprint.pprint(item)
        print ()

if __name__ == "__main__":
    main()

@ferdinand
Thanks for the response.

RE: we never expose managers themselves
Gotcha. Thanks for the clarification

RE: Code
Works as expected.

Closing this thread now.