administrators
Posts
-
RE: Import multiple Takes
Hey @yannickkohn,
Thank you for the source code, but pseudo code is often problematic, especially when it contains so many undefined functions. I cannot say much about any bugs, as your code is so 'pseudo' and you do not show the really deep down work (reading curves and keys here).
What also is a bit weird is that you use
FindOverride. That function is private for a reason. You should set the active take and then just evaluate the scene data or the tracks of scene data when you are interested in animations only.Cheers,
Ferdinand -
RE: Import multiple Takes
Hey Yannick, as I said without code and your scene data we will not be able to help you. In understand what you want to do conceptually, but for concrete help we will need concrete code and concrete data. As I hinted at, not all aspects of takes can be faithfully exported into the Melange (a.k.a.) Cineware format. The Take export has be initially written for the Adobe After Effects bindings, so there might be gaps even when data could be discretized in principle.
-
RE: Import multiple Takes
Hello @yannickkohn,
Welcome to the Maxon developers forum and its community, it is great to have you with us!
Getting Started
Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules.
- Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment.
- Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support.
- Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads.
It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: How to Ask Questions.
About your First Question
It is quite hard to answer your question in this form, please read the points listed above. From what I get, you have some C++ application and use there the Cineware SDK to import c4d files. You now want to read take data in these scenes. First of all, I would recommend to read the end user docs on takes, in case you have not already.
Takes are somewhat comparable to render settings in Cinema 4D, as in that you always have at least one of them in a scene, but also can have many (which also can be nested). Just likes for render settings, there can only be one active take at a time. So unless you have called SetCurrentTake, the data of your scene will not change.
Cineware is also a sparse/discrete data format, i.e., all procedural goodness of Cinema 4D has been baked down. Without knowing what take data you want to see being exported, it is hard to tell if what you are experiencing is working as intended or not. Please share your code and images or files of the scene you are trying to export, including examples/descriptions of what data is missing.
Cheers,
Ferdinand -
RE: how to detect obj selected in InExcludeData()?
Hey @chuanzhen,
Thank you for reaching out to us. For me this works fine, but I also struggled for a second with this. The crucial information is probably that you have to set
SEND_SELCHNGMSGin theInExcludeCustomGuifor which this shall work. Since this information is rather obscure, I have updated the docs ofInExcludeData::GetDatato better reflect this.Cheers,
Ferdinand -
RE: [Cinema 4D/Redshift] Nested Redshift Proxy Files Not Detected by Project Asset Inspector
Hello @vaishhg,
Welcome to the Maxon developers forum and its community, it is great to have you with us!
Getting Started
Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules.
- Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment.
- Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support.
- Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads.
It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: How to Ask Questions.
About your First Question
I assume this is about Deadline? I am also not sure that I understand the question correctly. Let me recap, so that we are sure we talk about the same thing.
You have a scene
Original.c4dand you export it to the Redshift Scene formatOriginalProxy.rs. Then you create a Cinema 4D sceneComposition.c4dand there create one or multiple Redshift Proxy objects referencingOriginalProxy.rs. Then you export that scene as a Redshift scene asCompositionProxy.rs. You now want to access information aboutOriginal.c4dorOriginalProxy.rswhen loadingCompositionProxy.rswith a RS Proxy object into a Cinema 4D scene (or by extension see that information in the Asset Inspector).That is not possible.
rsis the Redshift scene format which works across the full landscape of DCCs supported by Redshift. The Redshift format has no such concept as a generator and just discretizes all smooth/procedural geometry data.When you export a Cinema 4D scene to the Redshift
rsformat, it will among other things just walk your scene and collect all the geometry caches and save them discretely in the RS format. For Redshift it does not make any difference if it collects the cache of a Cube generator object or the cache of a Redshift Proxy generator object. In the eyes of Redshift these are both just two procedural geometry generators which must be discretized/baked for export (not entirely true, because Redshift Proxy objects are cached in the Redshift Core itself and not in Cinema 4D, but close enough).As soon as you save a scene in the
RSformat, all information is lost that something once was a generator and the parameters it held. The Redshift Core also does not know a concept such as asset data or the Asset Inspector, as that is a Cinema 4D specific concept. So, such data is not stored in thersformat either.So, to answer your questions: You cannot reach into the past like that. Neither directly via the Asset Inspector and its API, nor indirectly by for example traversing the scene graph of a scene. In fact, RS Proxy objects do not even have caches in the Cinema 4D world, unless you set Preview to Mesh. The actual data resides discretely in the in the Redshift Core.
As an example, when we have this scene which holds two proxies and we run this script on it to, print the scene graph string of each object in the scene, we can see both proxies only hold discrete polygonal data:
import c4d import mxutils doc: c4d.documents.BaseDocument # The currently active document. def main() -> None: """Called by Cinema 4D when the script is being executed. """ for obj in mxutils.IterateTree(doc.GetFirstObject(), True): print(mxutils.GetSceneGraphString(obj)) if __name__ == '__main__': main()
When we now save that scene as an RS scene file and load that in an RS Proxy object in another scene, we will see that it only contains one blob of discrete geometry.

Cheers,
Ferdinand -
RE: Finding out the latest asset version number/string via python
Hey @MPB,
there is no need to be sorry, sometimes one struggles even with very on the nose information. But the example is quite verbose, as it contains literally the words "version" and "timestamp" multiple times and explains how these concepts work.
But it is pointless to endlessly discuss this, it is quicker for me to just write what you want. Here is an example doing exactly what you want to do. Please understand that it is an exception that I write a code example when there is already an example which already explains the subject sufficiently as it is here the case.
Cheers,
FerdinandResult
What we also learn from this, is that the asset team works at unholy hours
.Latest version of asset file_266f97c45ea05f17 has version string '2.0.2 - 2022-07-30 02:29', version hash '4905fdf9a02aa951e0d18a6d07f244172a41205a4692b4ae065d6b856e5de7cb' and timestamp '2022-07-30 00:29:28'. Found 4 asset versions for asset id file_266f97c45ea05f17: Found asset version with version string '2.0.2 - 2022-07-30 02:29', version hash '4905fdf9a02aa951e0d18a6d07f244172a41205a4692b4ae065d6b856e5de7cb' and timestamp '2022-07-30 00:29:28'. Found asset version with version string '2.0.1 - 2022-02-03 23:45', version hash '3997955fa22c74286c9319509eeaa7a5dccd0230951b608fe338741bbce0d9f9' and timestamp '2022-02-03 22:45:45'. Found asset version with version string '2.0.0 - 2022-02-03 23:26', version hash '310c1a6684d8be9eafff1708225b64fe72bff46bd7fae8fa783c39fac7c70d43' and timestamp '2022-02-03 22:26:39'. Found asset version with version string '1.0.1 - 2022-02-02 03:02', version hash '5fafa425cbd3f951d4ce8859fc02f51857342094dd0c2fcac8eb4377b7cea9dd' and timestamp '2022-02-02 02:02:47'. Assets sorted by timestamp: file_266f97c45ea05f17/5fafa425cbd3f951d4ce8859fc02f51857342094dd0c2fcac8eb4377b7cea9dd (1.0.1 - 2022-02-02 03:02) file_266f97c45ea05f17/310c1a6684d8be9eafff1708225b64fe72bff46bd7fae8fa783c39fac7c70d43 (2.0.0 - 2022-02-03 23:26) file_266f97c45ea05f17/3997955fa22c74286c9319509eeaa7a5dccd0230951b608fe338741bbce0d9f9 (2.0.1 - 2022-02-03 23:45) file_266f97c45ea05f17/4905fdf9a02aa951e0d18a6d07f244172a41205a4692b4ae065d6b856e5de7cb (2.0.2 - 2022-07-30 02:29)Code
#coding: utf-8 """Provides an example for sorting assets by their time stamp metadata. """ __version__ = "2026.X.X" import c4d import maxon def main() -> None: """Runs the example for reading asset metadata. """ # Get the user preferences repository. repo: maxon.AssetRepositoryRef = maxon.AssetInterface.GetUserPrefsRepository() if not repo: raise RuntimeError("Could not access the user preferences repository.") # The id of the "Stone 01" asset which naturally has four asset versions. aid: maxon.Id = maxon.Id("file_266f97c45ea05f17") # Find explicitly the latest version of the asset. asset: maxon.AssetDescription = repo.FindLatestAsset( maxon.AssetTypes.File(), aid, maxon.Id(), maxon.ASSET_FIND_MODE.LATEST) # Get the time stamp and version hash and string of the latest asset version. metadata: maxon.AssetMetaData = asset.GetMetaData() timestamp: str = metadata.Get(maxon.ASSETMETADATA.ASSET_TIMESTAMP) version_hash: str = asset.GetVersion() version_string: str = maxon.AssetInterface.GetVersionString(asset) print(f"Latest version of asset {aid} has version string '{version_string}', " f"version hash '{version_hash}' and timestamp '{timestamp}'.") # Now find all versions of assets with the id #aid and print their metadata. assets: list[maxon.AssetDescription] = repo.FindAssets( maxon.AssetTypes.File(), aid, maxon.Id(), maxon.ASSET_FIND_MODE.ALL) print(f"\nFound {len(assets)} asset versions for asset id {aid}:") for item in assets: metadata = item.GetMetaData() timestamp = metadata.Get(maxon.ASSETMETADATA.ASSET_TIMESTAMP) version_hash = item.GetVersion() version_string = maxon.AssetInterface.GetVersionString(item) print(f"Found asset version with version string '{version_string}', " f"version hash '{version_hash}' and timestamp '{timestamp}'.") # So, if we wanted to temporally sort #assets, we could do this. The asset version is naturally # a hash, and there is no grantee that there is a version string or that that string is parsable # into a numeric value which could be sorted. assets.sort(key=lambda a: a.GetMetaData().Get(maxon.ASSETMETADATA.ASSET_TIMESTAMP)) print("\nAssets sorted by timestamp:") for item in assets: print(f"{item} ({maxon.AssetInterface.GetVersionString(item)})") if __name__ == "__main__": main() -
RE: Object-level "Show Help" (CMD+F1) for ObjectData plugins?
Hey @lasselauch,
Thank you for reaching out to us. I am not 100% sure that I am understanding you correctly. You basically want to hook into this menu entry, right?

That is not possible at the moment. Because what this thing does, is gather information from the description of the selected entity or the active dialog and with that data calls cinema::OpenHelpBrowser (at least the backend version of that function). This is not even a dedicated command, just a switch case within the abstracted dialog menu handling. So, this is custom built for
help.maxon.net.It would not be impossible to isolate this so that there could be either a dedicated plugin hook for this or it somehow reusing the existing
RegisterPluginHelpDelegate(the C++ variant of the Python hook you used). But that would be quite a bit of work, and you would also have to answer if that justifies the overhead of calling all hooks each time a user presses that button/menu entry (but you could also argue that the overhead ofRegisterPluginHelpDelegateis even worse).I can see the allure of "Show Help" working for third parties, but I doubt many people would use it and the current system is very Maxon centric which are not good arguments for going for this. On top of this, in theory, it would have to support both
NodeDataentities and dialogs (because the menu entry works for both). We could only support nodes, but there I would just recommend the proven and tested workflow of including a base description at the end of your nodes, which places there a bitmap icon branding that is clickable or just a button. I talked a bit in the all new Licensing Manual videos and code about this workflow.edit: An alternative could be to offer a hook into
OpenHelpBrowserbut there you probably then run into problems with dialogs as the back end function splits into two signatures (which do not exist in the frontend). Also solvable but again extra work that can hardly be justified but the few users this will have.I am not strictly against adding such hook, but I currently do not see a good cost/effect ratio unless this thread is flooded with third party developers stating otherwise.
Cheers,
Ferdinand -
RE: Finding out the latest asset version number/string via python
Hey,
as I already explained,
maxon.ASSET_FIND_MODE.LATESTensures that you find the last version of an asset. So this line of yours:asset_desc = repo.FindLatestAsset(maxon.AssetTypes.File().GetId(), temp_id, maxon.Id(), maxon.ASSET_FIND_MODE.LATEST)will retrieve the last asset version of an asset with the ID
temp_idwhich is of asset typeFile. If you would usemaxon.ASSET_FIND_MODE.ALLfor example and then also notFindLatestAssetbutFindAssets, you would find all assets that have the IDtemp_id.The id of an asset is not necessarily unique within a repository. It shares its ID with all other versions of that asset. Only the ID and version can uniquely identify an asset. And as said before, the version of an asset does not have to be a (quasi) numeric value as you assume it to be. The asset version is always a string, and in some cases, for example in the code example I linked to above, people put there something that could be parsed into a numeric value. But the asset version can also just be the string 'Bob's your uncle' or just some hash. So, you cannot sort assets temporally by their asset version. It is just another identifier that makes that version unique within the namespace of the asset ID.
If you want to temporally sort asset versions, first search for all assets with that ID, and then sort them using their timestamp. This, asset versioning, time stamps and other asset metadata, all has been extensively covered in the code example I already linked to above. Please read the example.
Cheers,
Ferdinand -
RE: Finding out the latest asset version number/string via python
Hello @MPB,
Welcome to the Maxon developers forum and its community, it is great to have you with us!
Getting Started
Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules.
- Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment.
- Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support.
- Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads.
It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: How to Ask Questions.
About your First Question
Without your code and the asset you are trying to read, helping youn concretely is impossible. Asset versioning is demonstrated pretty throughly in this code example.
I think your major misconception is that an asset version string has to be what you would consider a version descriptor, .e.g., "1.0". But that is absolutely not the case, and you can put there anything you want. The system will by default put there hashes; which is probably what you mean with "some kind of ID".
You must evaluate the date of last modification of each version of an asset to temporally order them. But that is all not really necessary when you just want to get the last version of an asset, as that is already baked into search operations with
maxon.ASSET_FIND_MODE.LATEST. I.e., when you have either an asset ID or an asset description, you just search for that asset ID and set the find mode to latest. See this example for a concrete case.You can also search for all versions of an asset and then sort them yourself via the time stamp (see also first example link). You can also access the other versions of an asset if you have just one asset description, as each asset links to its other versions with a list of asset-id-version tuples.
Cheers,
Ferdinand
