Solved How to get a port data type?

Hi community!

Questions:

How can I get the datetype of a selected port(GraphNode)?

Problem:

I want to get a type of a maxon.GraphNode aka a port type. Like picture below, I select three port with very basic port type, and I wang to get the type of the port to do some further conditions, but I have trouble with this task.

15ce3dae-6f50-4cf3-869f-5b6b1b1da5f0-image.png

I didn't find a api looks like build for this task , I try to get it with the codes and return like this, I can get color/ metalness which had a default value, but not the bump port. (the type returned is not like the GUI, but it can work.)

Color port

Name: standardmaterial@WO3Q2uk5Kp4pRHlNJ_Douc<com.redshift3d.redshift4c4d.nodes.core.standardmaterial.base_color
Value: 0.21404114365577698,0.21404114365577698,0.21404114365577698
ID: com.redshift3d.redshift4c4d.nodes.core.standardmaterial.base_color
Type: net.maxon.parametrictype.col<3,float64>

Metalness port

Name: standardmaterial@WO3Q2uk5Kp4pRHlNJ_Douc<com.redshift3d.redshift4c4d.nodes.core.standardmaterial.metalness
Value: 0
ID: com.redshift3d.redshift4c4d.nodes.core.standardmaterial.metalness
Type: float64

Codes:

import c4d
import maxon

def main():
    mat = doc.GetActiveMaterial()

    nodeMaterial = mat.GetNodeMaterialReference()

    nodespaceId = c4d.GetActiveNodeSpaceId()

    graph = nodeMaterial.GetGraph(nodespaceId)

    def GetName(node):

        if node is None:
            return None

        nodeName = node.GetValue(maxon.NODE.BASE.NAME)

        if nodeName is None:
            nodeName = node.GetValue(maxon.EffectiveName)

        if nodeName is None:
            nodeName = str(node)

        return nodeName

    def RetrieveInformationOfPort(port):

        if port is None:
            return True

        portName = GetName(port)
        portValue = port.GetDefaultValue()

        print(f"Name: {portName}")
        print(f"Value: {portValue}")
        print(f"ID: {port.GetId()}")
        print(f"Type: {portValue.GetType().GetId()}") 

        return True

    maxon.GraphModelHelper.GetSelectedNodes(graph, maxon.NODE_KIND.PORT_MASK, RetrieveInformationOfPort)

    c4d.EventAdd()

if __name__ == "__main__":
    main()

Thanks for your times.

Cheers~

Hello @Dunhou,

Thank you for reaching out to us. In C++, you would retrieve the attribute maxon::nodes::PortType (id: "type") on the node. There are also some attributes of similar purpose which return a maxon::DataType for a GraphNode.

However, none of these work, because there is a bug in maxon.DataType (i.e., the Python API reflection of maxon::DataType). Currently there is nothing you can do from the Python side of things to fix this. I have filed a bug report and flagged this thread as to_fix.

Cheers,
Ferdinand

Result:

GetName(port) = 'standardmaterial@Hg9$KeW8OFNmebDk8jn99C<com.redshift3d.redshift4c4d.nodes.core.standardmaterial.bump_input'
port.GetId() = maxon.InternedId('com.redshift3d.redshift4c4d.nodes.core.standardmaterial.bump_input')
<class 'maxon.datatype.DataType'> <NativePyData (net.maxon.datatype.datatype) [dt=0x00007FF7EC8692C0,data=0x000001A756F0A370,owner=false] object at 0x000001A756F0A340>
<class 'maxon.datatype.DataType'> <NativePyData (net.maxon.datatype.datatype) [dt=0x00007FF7EC8692C0,data=0x000001A756F02770,owner=false] object at 0x000001A756F02740>
<class 'maxon.datatype.DataType'> <NativePyData (net.maxon.datatype.datatype) [dt=0x00007FF7EC8692C0,data=0x000001A756F16670,owner=false] object at 0x000001A756F16640>

Code:

def RetrieveInformationOfPort(port: maxon.GraphNode) -> bool:
    """
    """
    if not isinstance(port, maxon.GraphNode):
        return False

    print (f"\n{'-' * 100}")
    print(f"{GetName(port) = }")
    print(f"{port.GetId() = }")

    # Try out various node attributes that express a type.
    for aid in ("type", "fixedtype", "synthesizedtype", "net.maxon.node.deducedtype"):
        # We can get these attributes, but they all return malformed data. There is a
        # bug in maxon.DataType itself (the type of all of these attributes).
        attribute: maxon.Data = port.GetValue(maxon.InternedId(aid))
        if attribute is None:
            continue
        
        print (type(attribute), attribute._data)

        # All these lines will fail, because #attribute is malformed in the Python API, 
        # its field DataType._data is not what it should be.
        
        # print(attribute)
        # print(attribute.GetId()) # This would be data type of the port.

MAXON SDK Specialist
developers.maxon.net

Hello @Dunhou,

Thank you for reaching out to us. In C++, you would retrieve the attribute maxon::nodes::PortType (id: "type") on the node. There are also some attributes of similar purpose which return a maxon::DataType for a GraphNode.

However, none of these work, because there is a bug in maxon.DataType (i.e., the Python API reflection of maxon::DataType). Currently there is nothing you can do from the Python side of things to fix this. I have filed a bug report and flagged this thread as to_fix.

Cheers,
Ferdinand

Result:

GetName(port) = 'standardmaterial@Hg9$KeW8OFNmebDk8jn99C<com.redshift3d.redshift4c4d.nodes.core.standardmaterial.bump_input'
port.GetId() = maxon.InternedId('com.redshift3d.redshift4c4d.nodes.core.standardmaterial.bump_input')
<class 'maxon.datatype.DataType'> <NativePyData (net.maxon.datatype.datatype) [dt=0x00007FF7EC8692C0,data=0x000001A756F0A370,owner=false] object at 0x000001A756F0A340>
<class 'maxon.datatype.DataType'> <NativePyData (net.maxon.datatype.datatype) [dt=0x00007FF7EC8692C0,data=0x000001A756F02770,owner=false] object at 0x000001A756F02740>
<class 'maxon.datatype.DataType'> <NativePyData (net.maxon.datatype.datatype) [dt=0x00007FF7EC8692C0,data=0x000001A756F16670,owner=false] object at 0x000001A756F16640>

Code:

def RetrieveInformationOfPort(port: maxon.GraphNode) -> bool:
    """
    """
    if not isinstance(port, maxon.GraphNode):
        return False

    print (f"\n{'-' * 100}")
    print(f"{GetName(port) = }")
    print(f"{port.GetId() = }")

    # Try out various node attributes that express a type.
    for aid in ("type", "fixedtype", "synthesizedtype", "net.maxon.node.deducedtype"):
        # We can get these attributes, but they all return malformed data. There is a
        # bug in maxon.DataType itself (the type of all of these attributes).
        attribute: maxon.Data = port.GetValue(maxon.InternedId(aid))
        if attribute is None:
            continue
        
        print (type(attribute), attribute._data)

        # All these lines will fail, because #attribute is malformed in the Python API, 
        # its field DataType._data is not what it should be.
        
        # print(attribute)
        # print(attribute.GetId()) # This would be data type of the port.

MAXON SDK Specialist
developers.maxon.net

@ferdinand thanks for your response.

Then only I can do now maybe pick a manual list with bump and displacement<vector> type port and considering with their ids.hope this will be fixed soon.

Cheers~

Hello @Dunhou ,

without further questions or postings, we will consider this topic as solved by Friday, the 11th of august 2023 and flag it accordingly.

Thank you for your understanding,
Maxon SDK Group

@jana Hey, I think this problem is not fixed now, I just test it with R2023.2.2.

Hello @Dunhou ,

you are correct, the issue is not fixed yet. As Ferdinand mentioned in the beginning he has flagged it as "to_fix", so it will be fixed as soon as possible.

Thanks and Cheers
Maxon SDK Group