mxutils_symboltranslationcache¶
Demonstrates translating Cinema 4D symbols with SymbolTranslationCache.
mxutils_symboltranslationcache.py¶
"""Demonstrates translating Cinema 4D symbols with SymbolTranslationCache.
Run this example in the Cinema 4D Script Manager. The cache discovers names for integer symbols
exposed by the c4d module.
Topics:
* mxutils.SymbolTranslationCache
* Cinema 4D symbols
"""
__author__ = "Ferdinand Hoppe"
__copyright__ = "Copyright (C) 2026 MAXON Computer GmbH"
__license__ = "Apache-2.0 License"
__version__ = "2027.0"
import c4d
import mxutils
def main() -> None:
"""Looks up selected object and data type symbols.
"""
# A symbol cache is just a class that caches the attribute names of integer attributes in an
# object and is meant to be used on modules. For the Cinema module there is global pre-built
# cache available as mxutils.g_c4d_symbol_translation_cache. You should normally avoid rebuilding
# such caches (as they are somewhat expensive to build) but for the sake of this example we will
# build a new cache for the c4d module.
myCache: mxutils.SymbolTranslationCache = mxutils.SymbolTranslationCache(c4d, buildDirectly=True)
# Two symbol IDs, which we would normally encounter somewhere in the API, for example we call
# GetType() on a BaseObject and it returns an integer, or we get a message ID from a message
# callback. We can use the cache to translate these IDs into their symbol names, which makes it
# then easier to understand what is happening when debugging your code.
cubeId: int = 5159 # The ID of c4d.Ocube
editMsgID: int = 21 # The ID of c4d.MSG_EDIT
# There are two ways to do this, __getitem__ and Get().
# __getitem__ returns all symbols that are associated with the given ID. For things like object,
# tag, material, etc type IDs, this will be enough, as they are 'usually' unique. For message IDs,
# there is a high chance that multiple symbols are associated with the same ID, so you will get a
# list of all of them.
cubeCandidates: list[str] | None = myCache[cubeId]
editCandidates: list[str] | None = myCache[editMsgID]
# Will print ['Ocube', 'OBJECT_CUBE']. 'OBJECT_CUBE' is one of the old legacy symbols.
print(f"Candidates for cube ID {cubeId}: {cubeCandidates}")
# Will print a LOT :)
print(f"Candidates for edit message ID {editMsgID}: {editCandidates}")
# The other way is to use Get(), which also allows us to provide a regex filter to narrow down the
# results. This is useful as we can often predict properties of the symbol, for example that node
# IDs always follow the pattern Xaaaaa, i.e., a capital letter followed by lowercase letters, that
# data type symbols always start with DTYPE_, or that node message symbols always start with MSG_.
cubeFiltered: list[str] | None = myCache.Get(cubeId, r"^[A-Z][a-z]+$")
editFiltered: list[str] | None = myCache.Get(editMsgID, r"^MSG_")
# Will print ['Ocube']
print(f"Filtered candidates for cube ID {cubeId}: {cubeFiltered}")
# Will print ['MSG_EDIT']
print(f"Filtered candidates for edit message ID {editMsgID}: {editFiltered}")
if __name__ == "__main__":
main()