0

Recreating the rv node structure in python

We are using RV 6.2.6 on Windows.

From python, I want to save out the current session, with some added metadata.

We haven't had much luck using the API to edit the current nodes in the session.

I had already implemented a class hierarchy to represent rv nodes in python.  Using this I can create a session from scratch and save out a .rv file that can be read back into rv.

I want to duplicate the rv DAG in my python fauxRV node objects.  I assume all relevant information is in the nodes and their properties, so I do this:

Get all rv node names.
For each rv node:
    Get all properties from the rv node
    Create a python fauxRV node and populate it with the properties 

This would appear to be the way to get all the rv data, but it doesn't seem to work properly.  When I save the current session and also save out my python nodes in .rv format, I notice some differences in the data I get from rv:
- The RVSession and RVSequenceGroup nodes are missing the "session" component.
- The RVSession node has an extra "opengl"  component (which is not understood when reading it back in).
- The connection node is not found
- The RVSequenceGroup is also missing the "session" component.
- I get a number of nodes that are not present in the rv saved session:
    RVDisplayPipelineGroup, RVDisplayStereo, and RVDisplayColor nodes.

It seems that from python, I may not be able to get an accurate picture of all rv data.  Is this true?   I'm about to write a parser to read a session file into my fauxRV classes so that I can edit it as needed and resave.

Am I missing something, or does python not have access to all the required data?

Thanks!

12 条评论

  • Avatar
    (Michael) Kessler 正式评论

    Hi Sumit,

     

    Wow!  Sounds like you've gone to some great lengths; let's see what we can do to help accomplish your goals.  I'm interested in what you are trying to accomplish, but if you'd rather not talk about the end-goal then I understand.

    First off; I'd love to know what problems you ran into with the API.  RV supports custom nodes and more used custom properties.  Custom properties are saved on either custom nodes or existing nodes and will be preserved through session writes/reads.  In python, you can create and populate a custom property like so:

    import rv

    session_node = rv.commands.nodesOfType("RVSession")[0]
    property_name = "%s.Autodesk.session_name" % session_node

    rv.commands.newProperty(property_name, rv.commands.StringType, 1)
    rv.commands.setStringProperty(property_name, ["Test"], True)

    If you run that on an active session then save the session you will find that writes out the key in the RVSession node:

    rv : RVSession (4)
    {
    matte
    {
    int show = 0
    float aspect = 1.33000004
    float opacity = 1
    float heightVisible = -1
    float[2] centerPoint = [ [ 0 0 ] ]
    }

    Autodesk
    {
    string session_name = "Test"
    }

    session
    {
    string viewNode = "defaultSequence"
    int[2] range = [ [ 1 2 ] ]
    int[2] region = [ [ 1 2 ] ]
    float fps = 24
    int realtime = 0
    int inc = 1
    int currentFrame = 1
    int marks = [ ]
    int version = 2
    }
    }


    In an interactive session, you can read a property with:

    rv.commands.getStringProperty(property_name)

    Which will return you an array of the strings in that property (in our case an array with one item that says "Test").

     

    As far as implementing your own DAG/parser; we already ship with a couple libraries that can help.  rvSession that ships with RV in the src folder is designed for programmatically assembling RV sessions like you describe.   In the rvSession folder in the src folder of RV's installation package are a couple useful files; rvSession.py is the high-level session authoring library for building nodes like you describe but maintaining connections and the like.  gtoContainer.py is the lower-level access that should allow you to read/write the container format without RV's specific knowledge; obviating the need for you to write a parser.

    As far as display nodes, those are intentionally not written to file because they contain hardware-specific settings; and relying on them in-between sessions is not considered safe practices.  Output groups which act similar to displays in some regard are preserved with the purpose being to act as a payload for output settings for RVIO.  It would be highly advisable in RV4 and later to use display profiles for your machines to reduce reliance on such payload.

    Let me know if I'm completely off-base here or if I can help clarify more.

    Thanks,

    -Kessler

  • 0
    Avatar
    Sumit Das

    Hi Kessler,

    Thanks for your quick reply!

    First, here's what I'm trying to accomplish:
    An artist has rendered some elements and loaded them into rv to view.  Once satisfied, they want to submit it to dailies.  This will mean saving the current session, but with added overlay text for show/sequence/shot/version/comments and things like that.

    I didn't know about rvSession.py, I'm embarrassed to admit.  I'll see if that does the job better than my classes, and I'll check out gtoContainer.py also.

    As far as what our API problems are, it's been a while so I don't remember... Let me try to work up a simple example.

    Thanks!

    -Sumit

  • 0
    Avatar
    Sumit Das

    Hi Kessler,

    I'm starting to look into all of this, but I would love to start using the API directly instead of our python classes. 

    Would it be possible for you to give some sample python code which could be run in an rv session that adds text metadata using an RVOverlay node?  One of my colleagues tried this and was not able to get it to work in the session using the API.

    Thanks, Sumit

  • 0
    Avatar
    Sumit Das

    Also, I understand the code you supplied, and I've been using rv.commands.nodesOfType and rv,commands.properties() to recreate the nodes.  But with the RVSession and connection node it gives strange results.

    rv.commands.nodesOfType("connection")

    Returns None.

    And,

    session_node = rv.commands.nodesOfType("RVSession")[0]
    print "\n".join(properties(session_node))

    Returns:
    rv.matte.show
    rv.matte.aspect
    rv.matte.opacity
    rv.matte.heightVisible
    rv.matte.centerPoint
    rv.opengl.GL_VERSION
    rv.opengl.majorVersion
    rv.opengl.minorVersion
    rv.opengl.GL_SHADING_LANGUAGE_VERSION
    rv.opengl.GL_VENDOR
    rv.opengl.GL_RENDERER
    rv.opengl.GL_MAX_TEXTURE_SIZE
    rv.opengl.GL_MAX_TEXTURE_BUFFER_SIZE
    rv.opengl.GL_MAX_TEXTURE_IMAGE_UNITS
    rv.opengl.GL_MAX_TEXTURE_COORDS
    rv.opengl.GL_MAX_TEXTURE_UNITS
    rv.opengl.GL_MAX_VERTEX_ATTRIBS
    rv.opengl.GL_MAX_DRAW_BUFFERS
    rv.opengl.GL_MAX_SAMPLES
    rv.opengl.GL_MAX_RECTANGLE_TEXTURE_SIZE
    rv.opengl.GL_MAX_3D_TEXTURE_SIZE
    rv.opengl.GL_EXTENSIONS

    So none of the properties in the "session" component (ie, rv.session.viewNode) show up.

    What am I missing here?

  • 0
    Avatar
    (Michael) Kessler

    Sure thing!

     

    Here's an example I just cooked up to write some sample text.  I utilized the Shotgun Python Console to quickly prototype this; which is available once SG Review is initialized under the 'Tools' menu:

     

    import rv.commands as rvc
    import rv.extra_commands as ec


    overlay = ec.nodesInEvalPath(rvc.frame(), "RVOverlay")[0]
    textName = "%s.text:example" % overlay

    position="%s.position" % textName
    rvc.newProperty(position, rvc.FloatType, 2)
    rvc.setFloatProperty(position, [.1, .1], True)

    color="%s.color" % textName
    rvc.newProperty(color, rvc.FloatType, 4)
    rvc.setFloatProperty(color, [1.0, .9, .6, 1.0], True)


    spacing="%s.spacing" % textName
    rvc.newProperty(spacing, rvc.FloatType, 1)
    rvc.setFloatProperty(spacing, [.8], True)

    size="%s.size" % textName
    rvc.newProperty(size, rvc.FloatType, 1)
    rvc.setFloatProperty(size, [.005], True)

    text="%s.text" % textName
    rvc.newProperty(text, rvc.StringType, 1)
    rvc.setStringProperty(text, ["Testing Overlay Text"], True)

    Starting from here you should see how to add additional properties if you so desire.  You can find additional available properties here:
    http://www.tweaksoftware.com/static/documentation/rv/current/html/rv_reference.html#RVOverlay

     

  • 0
    Avatar
    (Michael) Kessler

    Sumit,

     

    The connections are actually managed by changing the connections on nodes rather than managing them globally. 

    The following will give you the input and output connections on the specified node:

    rv.commands.nodeConnections(nodeName)

    Whereas if you want to wire up nodes, you utilize:

    rv.commands.setNodeInputs(nodeName, [inputNode1, inputNode2])

    Between those two you should be able to introspect and modify the DAG.

     

    As far as the current view; that is accessible from:

    rv.comands.viewNode()

    If there's something from the session you are looking for that isn't accessible from an accessor method; let me know and I can see what is available.

  • 0
    Avatar
    Sumit Das

    Thanks Michael, great info!

    But this:
    "I utilized the Shotgun Python Console to quickly prototype this; which is available once SG Review is initialized under the 'Tools' menu:"

    I didn't know about this!  Is it only available in RV version 7?  I don't see the Shotgun Review Package in 6.2.6

  • 0
    Avatar
    (Michael) Kessler

    Oh yes;  you would need to update your version for it; it also requires a Shotgun account.  That console is available in RV7.0+.  If you are a Shotgun user, then the latest version is available to you through your Shotgun subscription; so you should be able to update (or use that version for prototyping).  There is also the rvshell available in the src directory of your version that can connect to RV over a network that does not require Shotgun or SG Review.

    The Shotgun Python Console is based on an open source project I had put together, which you can find here: https://github.com/mikepkes/pyqtterm though the Shotgun Python Console brings a lot of polish from the Toolkit team and does the RV integration for you.

  • 1
    Avatar
    Sumit Das

    Hi Michael,

    You have been extremely helpful, and I have almost everything working well now.  Is there documentation of the python API and how to use the various calls anywhere?  I haven't seen very much.  I can look at the mu command browser for function descriptions, but is there a guide that gives context?   It would be very helpful to have python examples of simple (or not-so-simple) tasks to see more about how the different calls work together.

    One further question for my current task: What is the most reliable way to get the resolution of the currently displayed image?  My naive method from looking at the session files would be something like:

    import rv.commands as rvc
    stacks = rvc.nodesOfType("RVStack")
    res = rvc.getIntProperty("{0}.output.size".format(stacks[0]))

    But will that work in all cases?  I assume there is a more "correct" way to get this information.

    Thanks!

  • 0
    Avatar
    Sumit Das

    Ah, I found rv.commands.getCurrentImageSize(), so I assume that is the best call...


    So just two things remain and I will (attempt to) stop bothering you :)

    - As mentioned, python API documentation/examples
    - In the Shotgun Python Console, the current line of code is almost unreadable due to the color palette.  How can I change the text colors?

  • 0
    Avatar
    (Michael) Kessler

    Haha!

     

    The Python API docs are unfortunately the Mu api docs  (accessible from the Help>Mu Command API Browser).  They are almost a 1:1 match method for method in the commands/extra_commands modules.

    The Shotgun Python Console is, unfortunately, inheriting two color schemes from different places.  I've put in an internal bug ticket to fix the default.  The color scheme is computed from some colors but the inherited colors from RV's color-sensitive palette is not a good base for these adjustments.

    There's no currently supported way of changing the color palette, but since it is written with PySide it would be possible to inject your own palette with some digging into the widgets, but not recommended.

    If you want to start hacking on it, check out:

    import sgtk
    engine = sgtk.platform.current_engine()
    engine.apps['tk-multi-pythonconsole']

    That should let you start introspecting and finding your way, but this is an uncharted warranty-voiding area; if that sort of thing excites you then enjoy!

     

  • 0
    Avatar
    Sumit Das

    Thanks!  

    I'm not sure if I should put this in a separate thread, but is there a way to set the filename of the current session?
    I can get it but I can't set it.

    Also, it looks like in commands.saveSession(), the asACopy flag doesn't work.
    With this code:

     print("PREV Session file name is {0}".format(rvc.sessionFileName()))
    rvc.saveSession(tempFilePath, asACopy=True)
    print("THEN Session file name is {0}".format(rvc.sessionFileName()))

    The second print does not retain the original name of the session.

请先登录再写评论。