List all Redshift node types that can be added in Node Editor?
-
How to list all possible redshift node types that can be added in Node Editor, using Python?
-
Hello @vertexx,
Welcome to the Plugin Café forum and thank you for reaching out to us. As for all new forum members, I would recommend having a look at our Forum and Support Guidelines.
Your question is a bit ambiguous:
- You are talking about node types, with that you can either mean the node classification (Material, Surface, Light, Legacy, ...) or the node template/ node asset ID (Standard Material, Maxon Noise, Texture, ...). I assumed the latter here.
- You used here the term "Node Editor" which heavily implies the "new" node system, i.e., the Nodes API. You could also mean the old Xpresso based system, i.e., the GraphView API. I assumed here the former.
Strictly speaking, it is not possible to do in Python what you want to be done, because for that you would need the type
maxon::nodes::NodeTemplate
and its method ::Supports() to test if a given node template does support a given node system class (which more or less means node space in this context, e.g., the Redshift node space). This is fairly backend stuff which is only available in C++. We had not too long ago an internal question which wanted to associate a node space with node template asset, it shows how this would be done, see end of file.But there is also a cheap way to do this: Simply iterate over all node template assets and assume things based on their asset ID. This works fairly well, see the example at the end of my postings for details and drawbacks.
Cheers,
FerdinandPython
Result:
The created material contains 138 nodes, selecting all RS nodes in the Asset Browser returns 147 nodes. The difference are either cases where data type or mode variations of one node template are displayed in the Asset Browser, or the case that RS is using node templates that have not been exclusively written for the RS node space (see code).nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathrcpvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathabscolor' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.materiallayer' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathbiasvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.storecolortoaov' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsuserdatastring' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathsignvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.volume' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathatan2' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.standardmaterial' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathmixvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathtan' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rscolorcomposite' nodeId = 'com.redshift3d.redshift4c4d.node.osl' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathln' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathgainvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathmul' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathmodvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathnegvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.light_dome' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.architectural' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathsaturate' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.triplanar' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.displacementblender' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathinv' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.texturesampler' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.incandescent' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rshsv2color' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathasin' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.subsurfacescatter' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.environment' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathrange' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.physicalsun' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathgaincolor' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.displacement' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rscolormix' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathfloorvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathsqrt' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathrcp' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathabs' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.hair2' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.state' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.normalmap' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathsubvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathnormalizevector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathdiv' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathsqrtvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathexpcolor' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathadd' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.iortometaltints' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathmaxvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsuserdatavector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.carpaint' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathacos' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathrangevector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathdotvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.material' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathsin' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathsaturatevector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.bumpblender' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathsign' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.light' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.bumpmap' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.hair' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathsaturatecolor' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathfrac' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsscalarramp' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathabsvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rshairposition' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rayswitch' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.curvature' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathbiascolor' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsvectortoscalars' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.materialblender' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathmax' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.wireframe' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathinvvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.cameramap' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathcrossvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.fresnel' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathcos' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsshaderswitch' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathneg' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsuserdatacolor' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.light_ies' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.roundcorners' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.maxonnoise' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsuserdatainteger' nodeId = 'com.redshift3d.redshift4c4d.node.reference' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.uvprojection' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.light_portal' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rscolormaker' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathbias' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathdivvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathexp' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsnoise' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathaddvector' nodeId = 'com.redshift3d.redshift4c4d.node.output' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rscolorsplitter' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.c4dhairattribute' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathsub' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsramp' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rscolor2hsv' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.golaemhsl' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathmin' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathpow' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.matteshadow' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathsubcolor' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathmix' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.storescalartoaov' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.particleattributelookup' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathlnvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathlogvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathpowvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathexpvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.ambientocclusion' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.skin' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathgain' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathatan' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.vertexattributelookup' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathlengthvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathfracvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsvectormaker' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rscolorrange' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.storeintegertoaov' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rscolorlayer' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathmod' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathmulvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.hairrandomcolor' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rscolorcorrection' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathfloor' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rscolorconstant' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.physicalsky' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathminvector' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.sprite' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathlog' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsmathinvcolor' nodeId = 'com.redshift3d.redshift4c4d.nodes.core.rsuserdatascalar' len(rsNodeTemplateIds) = 138
Code:
"""Creates a RS node material which contains nodes for all RS node template assets which can be found in the user preferences repository. """ import c4d import maxon doc: c4d.documents.BaseDocument # The active document. def GetRsNodeTemplateIds() -> list[maxon.Id]: """Retrieves all node template assets in the user preferences repository that match the Redshift node prefix "com.redshift3d.redshift4c4d.nodes.". """ # Get the user preferences asset repository to search for the node templates. Technically, the # application repo should be here enough, but searching in the larger user preferences repo # does not really hurt either because the application repo is a subset of it. repo: maxon.AssetRepositoryRef = maxon.AssetInterface.GetUserPrefsRepository() if repo.IsNullValue(): raise RuntimeError("Could not access the user preferences repository.") # Get the latest version of all node template assets in the user preferences repository. nodeTemplateDescriptions: list[maxon.AssetDescription] = repo.FindAssets( maxon.Id("net.maxon.node.assettype.nodetemplate"), maxon.Id(), maxon.Id(), maxon.ASSET_FIND_MODE.LATEST) # This is how a native RS node template ID looks like, node template and node template asset IDs # are the same thing, so when one knows one of them, one knows both. # # "com.redshift3d.redshift4c4d.nodes.core.rsmathabscolor" # # With this information, we can infer what a native RS node space node template is by # searching for "com.redshift3d.redshift4c4d." as the prefix of a node template ID. The only # problem with this is, that we will not find any node templates with this approach which are # part of the standard node space and also happen to work in the RS node space. The only way out # of this is what I have shown in the C++ example with maxon::nodes::NodeTemplate::Supports() # but even that is a bit tricky. return [ item.GetId() # Each asset description has an ID, its asset ID. for item in nodeTemplateDescriptions if str(item.GetId()).startswith("com.redshift3d.redshift4c4d.") # Only pick the RS ones ] def main() -> None: """Runs the example. """ # Make sure that RS is the active node space. Doing this is not necessary for the # GetRsNodeTemplateIds(), we can retrieve node template assets just fine no matter which space # is active, but for creating functioning RS material, the RS space should be active (it is # technically also not required, but might confuse users otherwise). rsNodeSpaceId: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.class.nodespace") if c4d.GetActiveNodeSpaceId() != rsNodeSpaceId: raise RuntimeError("Make RS the active renderer and node space to run this script.") # Get all native RS node template IDs. rsNodeTemplateIds: list[maxon.Id] = GetRsNodeTemplateIds() # Create a node material and add a RS graph. material: c4d.BaseMaterial = c4d.BaseMaterial(c4d.Mmaterial) if not material: raise MemoryError(f"{material = }") nodeMaterial: c4d.NodeMaterial = material.GetNodeMaterialReference() graph: maxon.NodesGraphModelInterface = nodeMaterial.CreateDefaultGraph(rsNodeSpaceId) # Open a transaction and add every RS node template we have found to the graph, yikes! with graph.BeginTransaction() as gt: for nodeId in rsNodeTemplateIds: graph.AddChild(maxon.Id(), nodeId) # Also print the IDs while we are at it :) print(f"{nodeId = }") # Apply the changes. gt.Commit() print(f"{len(rsNodeTemplateIds) = }") # Insert the material, and add an update event. doc.InsertMaterial(material) c4d.EventAdd() if __name__ == "__main__": main()
C++
Result:
I cannot post the whole JSON dump here, but this is how one node template in it would be serialized.
Code:
Because this was intended as an internal example, it is not super granular in its comments./// @brief Dumps selected metadata of all assets in the user prefs repo into a JSON file. // classic API stuff #include "c4d_basedocument.h" #include "c4d_file.h" #include "c4d_general.h" // Basic maxon API stuff #include "maxon/datadescription_string.h" #include "maxon/parser.h" #include "maxon/stringencoding.h" #include "maxon/stringresource.h" // Nodes and Asset API stuff #include "maxon/assets.h" #include "maxon/basearray.h" #include "maxon/asset_keyword.h" #include "maxon/category_asset.h" #include "maxon/nodetemplate.h" #include "maxon/nodeslib.h" #include "maxon/node_spaces.h" #include "maxon/nodesystem_class.h" using NodeSystemClass = maxon::nodes::NodeSystemClass; ///< Alias for NodeSystemClass of the Node API. /// @brief Handles dumping a singular asset into a DataDictionary. class AssetDescriptionDump { private: maxon::AssetRepositoryRef _repo; ///< The lookup repo to search in when dumping. maxon::LanguageRef _language; ///< The language to search in, i.e., the language of dumped names, keywords, etc. maxon::AssetDescription _asset; ///< The asset to dump. const maxon::BaseArray<NodeSystemClass>* const _nodeSystemClasses; ///< The currently registered node system classes. public: /// @brief Constructor for the type with all necessary data. MAXON_IMPLICIT AssetDescriptionDump(const maxon::AssetRepositoryRef& repo, const maxon::LanguageRef& language, const maxon::AssetDescription& asset, const maxon::BaseArray<NodeSystemClass>* const nodeSystemClasses) : _repo(repo), _language(language), _asset(asset), _nodeSystemClasses(nodeSystemClasses) {} /// @brief The main method to dump wrapped asset into a DataDictionary. maxon::Result<maxon::DataDictionary> Dump() { iferr_scope; // Init the result dictionary and get the metadata. maxon::DataDictionary result; const maxon::AssetMetaData metadata = _asset.GetMetaData(); // Dump the simple stuff like id, name, etc. result.Set("id"_s, _asset.GetId().ToString()) iferr_return; result.Set("type"_s, _asset.GetTypeId().ToString()) iferr_return; result.Set("repo"_s, _asset.GetRepositoryId().ToString()) iferr_return; result.Set("url"_s, maxon::AssetInterface::GetAssetUrl(_asset, true).GetUrl()) iferr_return; result.Set("name"_s, _asset.GetMetaString(maxon::OBJECT::BASE::NAME, _language, ""_s)) iferr_return; result.Set("category"_s, GetNameFromId(maxon::CategoryAssetInterface::GetParentCategory(_asset))) iferr_return; // Dump the license flags and the version range of the asset into one string each. const maxon::ASSETLICENSETYPE license = metadata.Get(maxon::ASSETMETADATA::ValidLicenseType).GetValueOr( maxon::ASSETLICENSETYPE::NONE) iferr_return; result.Set("license"_s, GetLicenseInfo(license)) iferr_return; const maxon::ASSETMETADATA::VersionRange version = metadata.Get(maxon::ASSETMETADATA::ValidVersionRange).GetValueOr( maxon::ASSETMETADATA::VersionRange(0, 0)) iferr_return; result.Set("version_range"_s, version.ToString()) iferr_return; // Dump the keywords and the user keywords into one string each. const maxon::Array<maxon::Id> keywords = metadata.Get(maxon::ASSETMETADATA::Keywords, {}) iferr_return; const maxon::Array<maxon::Id> userKeywords = metadata.Get(maxon::ASSETMETADATA::UserKeywords, {}) iferr_return; result.Set("keywords"_s, GetKeywordInfo(keywords)) iferr_return; result.Set("user_keywords"_s, GetKeywordInfo(userKeywords)) iferr_return; // Dump asset dependencies into a singular string. const maxon::Array<maxon::AssetDependencyStruct> dependencies = metadata.Get( maxon::ASSETMETADATA::Dependencies, {}) iferr_return; result.Set("dependencies"_s, GetDependencyInfo(dependencies)) iferr_return; // Dump node spaces, or at least their closest related thing, node system classes into a string. This could be // done in a more complex manner, but I went here an easy route with some limitations. if (_asset.GetTypeId() == maxon::AssetTypes::NodeTemplate.GetId()) { result.Set("node_spaces"_s, GetNodeSytemInfo()) iferr_return; } return result; } /// @brief Returns the asset name for the asset with the asset ID #aid. maxon::Result<maxon::String> GetNameFromId(const maxon::Id& aid) { iferr_scope; if (aid.IsEmpty()) return "null"_s; const maxon::AssetDescription asset = _repo.FindLatestAsset(maxon::Id(), aid, maxon::Id(), maxon::ASSET_FIND_MODE::LATEST) iferr_return; if (MAXON_UNLIKELY(!asset)) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Could not find asset."_s); maxon::String name = asset.GetMetaString(maxon::OBJECT::BASE::NAME, _language, ""_s) iferr_return; return name; } /// @brief Removed maxon::Result<maxon::String> GetLicenseInfo(const maxon::ASSETLICENSETYPE& license) { iferr_scope; return ""_s; } /// @brief Converts a collection of keyword asset IDs into a comma-separated string of their asset names. maxon::Result<maxon::String> GetKeywordInfo(const maxon::Array<maxon::Id>& keywordIds) { iferr_scope; maxon::BaseArray<maxon::String> values; for (const maxon::Id& id : keywordIds) { const maxon::String s = GetNameFromId(id) iferr_return; values.Append(s) iferr_return; } return JoinString(values, ", "_s); } /// @brief Converts a collection of asset dependencies into a comma-separated string of names and types. maxon::Result<maxon::String> GetDependencyInfo(const maxon::Array<maxon::AssetDependencyStruct>& dependencies) { iferr_scope; maxon::BaseArray<maxon::String> values; for (const maxon::AssetDependencyStruct& d : dependencies) { values.Append(FormatString("@(@)", d.originalName, d.assetTypeId.ToString())) iferr_return; } return JoinString(values, ", "_s); } /// @brief Converts the supported node system classes of #_asset into a comma-separated string of IDs. /// @details Will raise an error for non-NodeTemplate assets. maxon::Result<maxon::String> GetNodeSytemInfo() { iferr_scope; if (MAXON_UNLIKELY(_asset.GetTypeId() != maxon::AssetTypes::NodeTemplate.GetId())) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Unsupported asset type."_s); maxon::BaseArray<maxon::String> values; // Load the template for _asset and check the node systems for support. maxon::nodes::NodeTemplate nodeTemplate = maxon::nodes::NodesLib::LoadTemplate( _repo, _asset.GetId()) iferr_return; for (const NodeSystemClass& cls: *_nodeSystemClasses) { const maxon::Bool doesSupport = nodeTemplate.Supports(cls) iferr_return; if (doesSupport) { values.Append(cls.GetId().ToString()) iferr_return; } } return JoinString(values, ", "_s); } /// @brief Joins an array of strings, basically works like Python's str.join(). maxon::String JoinString(const maxon::BaseArray<maxon::String>& data, const maxon::String& joinSymbol) { maxon::String result (""); maxon::Bool isStart = true; for (auto s : data) { if (isStart) { result += s; isStart = false; } else { result += (joinSymbol + s); } } return result; } }; /// @brief Runs the example by letting the user choose a directory, and then dumping the asset metadata of all assets /// both into a JSON and CSV file. static maxon::Result<void> Run(BaseDocument* doc) { iferr_scope_handler { ApplicationOutput("Error: @", err); return err; }; if (MAXON_UNLIKELY(!GeIsMainThread())) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "This method must run on the main thread."_s); // Let the user choose a directory to dump data to. Filename directory; if (!directory.FileSelect(FILESELECTTYPE::ANYTHING, FILESELECT::DIRECTORY, "Dump to:"_s)) return maxon::OK; StatusSetSpin(); StatusSetText("Gathering node systems and assets."_s); // In order to somewhat evaluate node spaces, we must dig around quite deep in the maxon API. To // do that we must find all NodeSystemClass instances. There is no registry/namespace for them, so // we must iterate over ALL classes. We should really cache that, because if we do this for each // asset, this will take ages. Nicked from the Asset Browser, so this indeed seems to be the only // way to do this atm. maxon::BaseArray<NodeSystemClass> nodeSystemClasses; for (const maxon::Class<>& cls : maxon::Classes::GetEntries()) { // Skip over everything that is not a node system impl. if (!cls.IsSubclassOf(maxon::nodes::DefaultNodeSystemClass().GetClass())) continue; // And add the id of that class to the output. NodeSystemClass nsCls = reinterpret_cast<const maxon::Class<NodeSystemClass>&>(cls).Create() iferr_return; nodeSystemClasses.Append(nsCls) iferr_return; } // Pick a lookup directory and get all (latest) assets. const maxon::AssetRepositoryRef repo = maxon::AssetInterface::GetUserPrefsRepository(); if (MAXON_UNLIKELY(!repo)) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Could not access user repository."_s); maxon::BaseArray<maxon::AssetDescription> foundAssets; repo.FindAssets(maxon::Id(), maxon::Id(), maxon::Id(), maxon::ASSET_FIND_MODE::LATEST, foundAssets) iferr_return; // Start building the data by iterating over the assets. maxon::DataDictionary assetData; maxon::LanguageRef language = maxon::Resource::GetDefaultLanguage(); maxon::Int32 totalCount = (Int32)foundAssets.GetCount(); maxon::Int32 i = 0; for (maxon::AssetDescription& asset : foundAssets) { StatusSetText(FormatString("Dumping asset (@/@): @", ++i, totalCount, asset.GetId())); AssetDescriptionDump dumper (repo, language, asset, &nodeSystemClasses); maxon::DataDictionary dict = dumper.Dump() iferr_return; assetData.Set(asset.GetId(), dict) iferr_return; } // Write the data to JSON. StatusSetText("Writing data to JSON."_s); maxon::ParserRef json = maxon::ParserClasses::JsonParser().Create() iferr_return; if (MAXON_UNLIKELY(!json)) return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Could not create JSON parser."_s); maxon::Url url = (MaxonConvert(directory, MAXONCONVERTMODE::NONE) + maxon::Url("asset_dump.json"_s)) iferr_return; json.WriteFile(url, maxon::StringEncodings::Utf8(), assetData, true) iferr_return; ApplicationOutput("Wrote JSON dump for @ assets to: @", totalCount, url); StatusClear(); return maxon::OK; }
-
Great, this is exactly what I needed. Thanks @ferdinand !