Load presets args in python?
-
Hey Community,
I want to load some presets args for special objects, e.g, implement the function of selecting and loading preset buttons
but I look the assets api handbook and the preset example, it need aPresetLoadArgs
but it seems not valid in python.How can I achieve similar effects in existing versions?
Cheers~
DunHou -
Hey @Dunhou,
Thank you for reaching out to us. No, you do not need
PresetLoadArgs
, these are only required when you want to handle preset asset drag events. To load a preset, you just needmaxon.AssetCreationInterface
, which has been wrapped for Python. The primary method to use for this would beGetDefaultSettings
, which unfortunately is broken. I provide below a workaround withmaxon.AssetCreationInterface.GetDefaultObject
.Depending on what you want to do
GetDefaultObject
will work fine (when you just have to load a handful of predefined presets) or a bit clunky (when you have to discover all preset assets for a given scene element type).Because this concerns a bug, I have moved the topic.
Cheers,
FerdinandResult
Code
"""Demonstrates how the find and apply preset assets. For this script to work sensibly, you should have a few preset assets for the Cube object, as accessible with the preset dropdown in the top right corner of the Attribute Manager. """ import c4d import maxon doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. def main() -> None: """Called by Cinema 4D when the script is being executed. """ # Get the global asset repository and all preset assets in it. repo: maxon.AssetRepositoryRef = maxon.AssetInterface.GetUserPrefsRepository() presets: list[maxon.AssetDescription] = repo.FindAssets( maxon.AssetTypes.DefaultsPreset(), maxon.Id(), maxon.Id(), maxon.ASSET_FIND_MODE.LATEST) # Now iterate over all assets in it: for i, asset in enumerate(presets): c4d.gui.StatusSetBar(float(i) / float(len(presets))) c4d.gui.StatusSetText(f"Processing {i + 1} of {len(presets)} assets...") # Get the name of the asset. name: str = asset.GetMetaString(maxon.OBJECT.BASE.NAME, maxon.Resource.GetCurrentLanguage(), "") # This is how we would do this normally, but #GetDefaultSettings is brokeen. #types would # hold the BaseList2D types #asset is applicable to, and #settings would hold the data # container for the preset. # types: maxon.BaseArray[maxon.Int32] = maxon.BaseArray(maxon.Int32) # settings: c4d.BaseContainer = c4d.BaseContainer() # maxon.AssetCreationInterface.GetDefaultSettings(asset, types, settings) # As a workarround, we can do this, which even without inserting the nodes, is very much # not a cheap operation. Doing this for a handful of assets (e.g., a list of hard-coded # presets) is fine, but for all of them, it takes a while. op: c4d.BaseList2D = maxon.AssetCreationInterface.GetDefaultObject(asset) if not op: continue # We found an Ocube asset. if op.CheckType(c4d.Ocube): op.SetName(name) doc.InsertObject(op) c4d.gui.StatusClear() c4d.EventAdd() if __name__ == '__main__': main()
-
F ferdinand moved this topic from Cinema 4D SDK on
-
Hey @ferdinand ,
Thanks for the tips, sadly to see that GetDefaultSettings is broken, and I tried GetDefaultObject. It is way too slow, so I had to give up this until GetDefaultSettings fixed.
Thanks for your time
Cheess~
DunHou -
You could just do it in a thread in the background to cache the information.
-
yes, but I want to use it in my own dialog, it needs to be as fast as normal drop down, but it is not a necessary function so I can wait for this.
-
well, that would not change anything about you being able to cache this. When your dialog is being opened, you start a thread which collects that information, and you then build your layout first without that information (i.e., empty combo boxes or wherever you want to put that information), when the thread is done, you invoke a layout rebuild which then uses that new information. You could of course also start the data collection earlier, e.g., when C4DPL_STARTACTIVITY is emitted. But make sure that you then call there WaitForDatabaseLoading.
-
It sounds worth a try, but there may be latency issues when it comes to changes, or data changes can be manually processed during the changes
Perhaps for my needs, I can force the database to be use GetSceneRepository, anyway, it's worth a try. Thank you for your guidance