Question. DFG Port->Custom PySide Widget

AlexanderMAlexanderM Posts: 132 ✭✭

Hi,
Is there a short way to set DFG port data to custom PySide widget? I'm talking about Widget customisation using Python

Let's say NO to Autodesk®Fabric®

Comments

  • AlexanderMAlexanderM Posts: 132 ✭✭

    l suspect an answer must be somethere here https://github.com/fabric-engine/FabricUI/tree/degas/DFG

    Let's say NO to Autodesk®Fabric®

  • borjaborja Administrator, Fabric Employee Posts: 468 admin

    Hi @AlexanderM

    Would you mind to be more specific on what are you trying to achieve? It is not clear for us at this point.

    Borja Morales
    Technical Product Manager
    Fabric Software Inc.

  • AlexanderMAlexanderM Posts: 132 ✭✭

    I'm trying to create an image viewer widget, I want to connect Image2DColor data and draw it using Qt tools

    Let's say NO to Autodesk®Fabric®

  • JulienCouetJulienCouet Fabric Employee Posts: 10 Fabric Employee

    Hello Alexander.

    You can use the python version of the DFGUICmd_SetPortDefaultValue command : setPortDefaultValue defined in FabricUI/Python/Canvas/BindingWrapper.py. The BindingWrapper is used to make our commands scriptable in Python. It's owned by the ScriptEditor (FabricUI/Python/Canvas/ScriptEditor.py) that is defined in CanvasWindow (FabricUI/Python/Canvas/CanvasWindow.py)

    def setPortDefaultValue(
            self,
            execPath,   --> Path of the DFGExec  (node) you want to set the port 
            portPath,   --> Name of the port 
            val,        --> RTVal type : (String, Xfo, ...)
            valueJSON,  --> RTVal value as Json (See http://docs.fabric-engine.com/FabricEngine/2.4.0/HTML/RTValProgrammingGuide/python.html
            ):
            rootExec = self.binding.getExec()
            exec_ = rootExec.getSubExec(execPath)
            value = self.rtvalEncoderDecoder.getFromString(typeName, valueJSON)
            cmd = DFG.DFGUICmd_SetPortDefaultValue(
                self.binding,
                execPath,
                exec_,
                portPath,
                value)
            InvokeCmd(cmd, self.qUndoStack)
    

    Because setting the port value using the Json representation of the RTVal can be tricky, you could add this method in FabricUI/Python/Canvas/BindingWrapper.py.

    def setPortDefaultValueFromRTVal(
            self,
            execPath,  
            portPath,    
            rtValue
            ):
            rootExec = self.binding.getExec()
            exec_ = rootExec.getSubExec(execPath)
            cmd = DFG.DFGUICmd_SetPortDefaultValue(
                self.binding,
                execPath,
                exec_,
                portPath,
                rtValue)
            InvokeCmd(cmd, self.qUndoStack)
    

    Then, you can, from your widget, call this method using the following code path :

    def MyWidget(QtGui.QWidget):
    
        def __init__(self, scriptEditor):
            # Gets a reference to the binding wrapper
            self.bindingWrapper = scriptEditor.eval_globals['binding']
            self.bindingWrapper.setPortDefaultValueFromRTVal(.....)
    
        .....
    
    myWidget = MyWidget(canvasWindow.scriptEditor)
    
    

    Let us know if it helps.

    Julien.

  • scaronscaron Fabric for Houdini Posts: 167

    @JulienCouet Thanks for this! You guys have done so much stuff that sometimes it is hard to see how this all can be used.

  • AlexanderMAlexanderM Posts: 132 ✭✭

    Hi Julien,
    I'm trying to build a simple widget with your solution. I want it to show a Float32 value in LCD, but I need more info how to do that. Current code is:
    `

    scriptEditor = mainWin.scriptEditor
    class TestWindow(QtGui.QWidget):
        def __init__(self,scriptEditor):
            super(TestWindow, self).__init__()
            self.resize(500, 500)
            self.setWindowTitle('ImageViewer')
            self.bindingWrapper = scriptEditor.eval_globals['binding']
            rtVal = client.RT.types.Float32()
            self.bindingWrapper.setPortDefaultValueFromRTVal("", "testView", rtVal)
            lcd = QtGui.QLCDNumber(self)
            lcd.resize(100, 50)
            lcd.display(rtVal.getSimpleType())
    

    `

    Let's say NO to Autodesk®Fabric®

  • JulienCouetJulienCouet Fabric Employee Posts: 10 Fabric Employee
    edited April 18

    Hello Alexander.

    Excuse me, but I am a bit confused.
    Do you want to update the content of the LCD display when the value of the node changes, or the opposite?

  • AlexanderMAlexanderM Posts: 132 ✭✭

    Hi Julien,
    Yes, I want to get data from node/port and use it in my custom widget. The main goal is to show Image2DColor data in my custom widget (as I showed it on the picture above), I want to make something like procedural texture viewer.
    The start test goal is to display just one Float32 value in LCD widget. Is it hard to realize this at current Fabric UI stage?

    Let's say NO to Autodesk®Fabric®

  • JulienCouetJulienCouet Fabric Employee Posts: 10 Fabric Employee

    Hello Alexander.

    Excuse me for the misunderstanding. We can suggest you two approaches:
    First, you can create a custom item for the value editor from where the image viewer is opened.
    In this case, the Image2DColor is set from the node port and no KL changes is involved.

    Secondly, you can use a KL singleton containing the Image2DColor, singletons are accessible from both KL and Cpp/Python.
    To set the image content, you can create a DFG Node that sets the singleton, and get it in the image viewer widget.
    Canvas application has a signal 'dirty' that can but connected to your custom widget to know when to update its content.

    Let us know which one you prefer so we can guide you.

    Julien.

  • AlexanderMAlexanderM Posts: 132 ✭✭

    Hi Julien,
    Both ways are interesting and look nice. May you tell details about the first case?

    Let's say NO to Autodesk®Fabric®

  • AlexanderMAlexanderM Posts: 132 ✭✭
    edited April 24

    I have another question. Is there a way to make signal/controller from specific port (by path and name)? I mean something like "controller.topoDirty.connect(...)", but from specific port, not from whole "dfgWidget". My goal is to make signal to my widget if port is connected or disconnected.
    I want to add a port with specific name and connect their state signals (isConnected, isChanged...or something else) to trigger of my widget.

    Let's say NO to Autodesk®Fabric®

  • AlexanderMAlexanderM Posts: 132 ✭✭

    Well, I noticed that Python's FabricUI is very limited than real FabricUI, there is lot of methods are not available. I tried to get mainWin.dfgWidget.getGraphViewWidget() then graph(), port(FTL::StrRef name), isConnected()

    Let's say NO to Autodesk®Fabric®

Sign In or Register to comment.