🆕 Two new dev libs in pyRevit: `revit.avf` and `revit.tmpgfx`

Hey all — a few weeks ago I added two new helper libraries to pyRevit’s pyrevit.revit module that make two previously painful Revit APIs actually usable from a script. Both ship with runnable examples in pyRevitDevTools.extension → Developer Examples panel, so you can try them right now without writing a line of code.


1. pyrevit.revit.avf — paint numbers onto elements (heatmaps & value overlays)

Revit’s Analysis Visualization Framework (AVF) is what’s under the hood of tools like solar/energy analysis — it lets you overlay numeric values on element faces as text markers or as a color gradient. The raw API (SpatialFieldManager, AnalysisResultSchema, face-reference wrangling…) is a lot of boilerplate for something that’s genuinely useful for QA/QC markers, KPI overlays, or just visualizing “here’s a number per element” in 3D.

avf.py wraps all of that into a handful of functions:

  • display_avf_values(element_value_dict, view, ...) – give it a {element: value} dict and a view, it finds a viewer-facing face on each element (or bbox center as fallback) and paints the value on it.
  • update_avf_values(...) – cheap re-update of existing values without re-searching geometry (e.g. for a live-refresh tool).
  • display_avf_values_at_points(...) – for point-cloud style overlays not tied to any element, auto-chunked per Revit’s recommended primitive size.
  • get_or_create_marker_display_style(...) / get_or_create_colored_surface_display_style(...) – get-or-create helpers for the two display styles (text markers vs. gradient heatmap).
  • clear_avf_results(view) / remove_avf_primitive(...) – cleanup, since AVF results live only for the session and aren’t saved with the model.

Minimal usage example (full version in the Developer Examples panel — pick an element, type a value, choose a style, done):

from pyrevit import revit
from pyrevit.revit import avf

values = {wall1: 12.5, wall2: 44.0}

# marker style = discrete/inspectable values
# colored-surface style = continuous/comparative values (heatmap)
style = avf.get_or_create_marker_display_style(revit.doc, "MyTool_AVF")

with revit.Transaction("Show values"):
    revit.active_view.AnalysisDisplayStyleId = style.Id
    results = avf.display_avf_values(values, revit.active_view, unit="ea")

# later, e.g. before recomputing:
avf.clear_avf_results(revit.active_view)

Good fits: QA/QC flags per element, occupancy/load overlays, any “show a computed number on the model” workflow — without dumping everything into a schedule or tags.

Code: pyrevitlib/pyrevit/revit/avf.py
Demo: Developer Examples.panel/AVF.pushbutton
Recording2026-07-30220758-ezgif.com-video-to-webp-converter


2. pyrevit.revit.tmpgfx — clickable in-canvas icons

This one wraps Revit’s TemporaryGraphicsManager / ITemporaryGraphicsHandler — the API behind clickable in-canvas icons (think: warning glyphs floating over elements that you can click to trigger a callback). It’s a neat, under-used API for building interactive QA tools directly in the 3D/plan view instead of a separate dialog.

tmpgfx.py gives you two building blocks:

  • Handler — a base ITemporaryGraphicsHandler you subclass and override on_click(index, payload) on. Registers itself with Revit’s external service automatically.
  • ControlManager — wraps TemporaryGraphicsManager per-document, tracks controls per-view so you can clear them selectively, and adds quality-of-life methods: add_control, remove_control, clear/clear_all, set_visibility/set_visibility_all, update_control, plus sync() and remove_all_untracked() to recover/clean up controls left behind by a previous script run (e.g. after a pyRevit reload).

Minimal usage example (full version in the Developer Examples panel places a warning icon on a picked element — click it to see element info in a TaskDialog):

from pyrevit.revit.tmpgfx import ControlManager, Handler

class MyHandler(Handler):
    def on_click(self, index, payload):
        # payload is whatever you passed to add_control()
        TaskDialog.Show("Clicked", str(payload))

mgr = ControlManager(doc, handler=MyHandler())
mgr.add_control(icon_path, position, view, payload=my_elem)

# ... later ...
mgr.clear(view)
mgr.unregister()

Icons are 24-bit BMPs (32x32 or 64x64 recommended); use RGB(0, 128, 128) as the background color in the bitmap to get a transparent-icon effect.

Good fits: in-canvas flags/markers with click-to-inspect behavior, lightweight “click this icon to run an action on this element” tools, session-scoped visual QA overlays.

Code: pyrevitlib/pyrevit/revit/tmpgfx.py
Demo: Developer Examples.panel/TemporaryGraphics.pushbutton
Recording2026-07-30221034-ezgif.com-video-to-webp-converter


Both are on develop now. Happy to take feedback/PRs if anyone wants to extend them (multi-value AVF schemas, animated tmpgfx icons, etc.). If you build something with either, would love to see it!

Wonderful work. Thanks the samples as well!