HOM Feed Example: Part 3 Implementation

The final part of this example sets a pick script on the geometry object. This script runs when you click on the object in the viewport, and it launches the corresponding URL in Houdini’s help browser.

Remember to start Houdini from the same directory containing the feedloader and feedparser modules.

Location

Supporting files for this example are in $HFS/mozilla/documents/hom/cookbook/feed/part3, also found in the cookbook/feed/part3 directory of cookbook_files.tar.gz.

Code

For this part of the example, we’ll move the code into the hou.session module. The shelf button will simply call a hou.session function, and the geometry object pick scripts will also call a function there.

Shelf code:

hou.session.createObjects()

hou.session:

# The webbrowser module is distributed with Python.  The feedloader module
# is part of this example and its code is listed below.
import webbrowser
import feedloader

use_help_browser = False

links = []

def openLink(index):
    """Open the URL for a given link index."""
    openURL(links[index][1])

def openURL(url):
    """Open a given URL in the browser."""
    if use_help_browser:
        # If a help browser is already open, use it.
        desktop = hou.ui.curDesktop()
        browser = desktop.paneTabOfType(hou.paneTabType.HelpBrowser)
        if browser is None:
            browser = desktop.createFloatingPane(hou.paneTabType.HelpBrowser)
        browser.setUrl(url)
    else:
        webbrowser.open_new(url)

def createObjects():
    """Load the RSS feed and create objects containing the titles.  When
       you click on the objects, they'll open the link in the browser.
    """
    # Load from an RSS feed into the links global variable, storing
    # (title, url) tuples.
    global links
    links = feedloader.loadLinks()

    # Delete all the existing objects in /obj.
    for child in hou.node("/obj").children():
        child.destroy()

    y_pos = 0
    for index in range(len(links)):
        text, url = links[index]

        geo = hou.node("/obj").createNode("geo", run_init_scripts=False)
        font = geo.createNode("font")
        font.parm("text").set(text)

        color = geo.createNode("color")
        color.setFirstInput(font)
        color.parmTuple("color").set((0, 0, 0))
        color.setDisplayFlag(True)

        geo.parm("ty").set(y_pos)
        y_pos -= 2
        geo.parm("pickscript").set(
            'python -c "hou.session.openLink(%d)"' % index)
    hou.node("/obj").layoutChildren()

For reference, the contents of the feedloader module are listed below. The feedloader module is part of this example, and it internally uses the feedparser module from to download a particular RSS news feed. It then discards non-ascii characters and decodes html-encoded characters. It also lets you read from a file instead of a feed, in case you don’t have internet access.

:

"""Set use_file to True to read from a file on disk instead of from a real
   RSS feed.
"""
use_file = False

import htmllib

def textToAscii(text):
    """Convert unicode, HTML-encoded text into ASCII so Houdini can
       understand it."""
    # First decode the html escaped portions.
    parser = htmllib.HTMLParser(None)
    parser.save_bgn()
    parser.feed(text)
    decoded_text = parser.save_end()

    # Now discard non-ascii characters.
    return "".join(x for x in decoded_text if 32 <= ord(x) < 128)

def loadLinks(url="http://news.google.com/news?ned=us&topic=t&output=rss"):
    """Return the contents of an RSS feed in the form of (title, url) tuples."""
    if use_file:
        return _loadLinksFromFile()

    # Print out a message in case it takes a long time to download the feed,
    # or in case we're not connected to the internet.
    import feedparser
    print "downloading feed..."
    document = feedparser.parse(url)
    print "...done"

    links = []
    for entry in document['entries']:
        title = textToAscii(entry['title'])
        url = textToAscii(entry['link'])
        links.append((title, url))
    return links

def _loadLinksFromFile(file_name="sample_links.txt"):
    """Pretend to load an RSS feed by reading from a file."""
    links = []

    f = file(file_name, "r")
    while True:
        title = f.readline().rstrip("\n")
        if not title:
            break;
        url = f.readline().rstrip("\n")
        links.append((title, url))
    f.close()

    return links

Visit for information about the feedparser module.

Previous: part 2