Skip to content

FamSlide — live parameter sliders for the Family Editor - #3489

Open
Wurschdhaud wants to merge 12 commits into
pyrevitlabs:developfrom
Wurschdhaud:new-
Open

FamSlide — live parameter sliders for the Family Editor#3489
Wurschdhaud wants to merge 12 commits into
pyrevitlabs:developfrom
Wurschdhaud:new-

Conversation

@Wurschdhaud

Copy link
Copy Markdown
Contributor

Description

What this is

FamSlide gives you a modeless panel of sliders / checkboxes / textboxes bound
to the active family's parameters, so you can see how the model reacts to
parameter changes (shape changes, constraint errors, etc.) without
round-tripping through the Family Types dialog every time. It also has
one-click "shuffle all values" and "delete unused parameters" utilities.

This is effectively a reimplementation of Archilizer's Family Editor
Interface
, which unfortunately hasn't been updated
for Revit versions newer than 2024.
Credit to Archilizer for the original
concept and UX — this tool exists to keep that workflow alive on current
Revit.

What's in this PR

  • Modeless WPF panel, reactive to doc-changed / view-activated /
    doc-opened so the parameter list stays in sync as you edit, undo/redo, or
    switch between open families.
  • Grouped view (Value / BuiltIn / Yes-No) with tag pills (in use, uF
    used-in-formula, dF driven-by-formula, built-in, instance/type,
    associated).
  • Shuffle-all and delete-unused-parameters bulk actions, both confirmed and
    wrapped in a single transaction.
  • Full 8-language localization (en_us, ko, fr_fr, ru, chinese_s,
    es_es, de_de, pt_br) for both bundle metadata and in-panel UI text.

Screenshots / recording

image
Recording.2026-07-16.094834.mp4

Checklist

Before submitting your pull request, ensure the following requirements are met:

  • Code follows the PEP 8 style guide.
  • Code has been formatted with Black using the command:
    pipenv run black {source_file_or_directory}
  • Changes are tested and verified to work as expected.

@jmcouffin
jmcouffin requested a review from Copilot July 16, 2026 07:59
@jmcouffin jmcouffin self-assigned this Jul 16, 2026
@jmcouffin jmcouffin added the Tools Issues related to pyRevit commands [subsystem] label Jul 16, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new pyRevitTools Family Editor utility (“FamSlide”) that provides a modeless WPF panel for interactively editing family parameters (sliders/checkboxes/text) with localized UI strings and a couple of bulk actions.

Changes:

  • Introduces the FamSlide modeless WPF window and Revit event wiring to keep the parameter list in sync.
  • Adds parameter discovery/classification utilities plus bulk actions (shuffle values, delete unused).
  • Adds 8-language localization resources and registers the new pushbutton in the Family pulldown.

Reviewed changes

Copilot reviewed 14 out of 16 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/script.py Main modeless WPF UI + event hooks + commit logic for parameter edits.
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/FamSlideWindow.xaml XAML layout for the FamSlide window.
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/FamSlideWindow.ResourceDictionary.en_us.xaml English UI string resources for in-panel localization.
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/FamSlideWindow.ResourceDictionary.ko.xaml Korean UI string resources for in-panel localization.
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/FamSlideWindow.ResourceDictionary.fr_fr.xaml French UI string resources for in-panel localization.
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/FamSlideWindow.ResourceDictionary.ru.xaml Russian UI string resources for in-panel localization.
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/FamSlideWindow.ResourceDictionary.chinese_s.xaml Simplified Chinese UI string resources for in-panel localization.
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/FamSlideWindow.ResourceDictionary.es_es.xaml Spanish UI string resources for in-panel localization.
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/FamSlideWindow.ResourceDictionary.de_de.xaml German UI string resources for in-panel localization.
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/FamSlideWindow.ResourceDictionary.pt_br.xaml Brazilian Portuguese UI string resources for in-panel localization.
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/famslide_paramutils.py Parameter scanning/classification/tagging and default slider ranges.
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/famslide_actions.py Bulk actions: shuffle values and delete unused parameters.
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/bundle.yaml Pushbutton metadata, localized tooltip, and persistent engine requirement.
extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/bundle.yaml Adds FamSlide to the Family pulldown layout.

@devloai devloai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Summary:

  • Adds FamSlide, a modeless WPF panel exposing live sliders/checkboxes/textboxes bound to the active family's parameters in the Family Editor.
  • Reactive refresh on doc-changed / view-activated / doc-opened, plus "shuffle all values" and "delete unused parameters" bulk actions (transaction-wrapped, confirmed via forms.alert).
  • Full 8-locale localization for bundle metadata and in-panel UI strings via ResourceDictionary XAML files.

Review Summary:

Reviewed script.py, famslide_paramutils.py, famslide_actions.py, bundle.yaml, and the XAML/localization files. The pyrevit.revit.events.execute_in_revit_context bridging pattern and the module-level ui = None + engine: persistent: true singleton idiom are used correctly and match established, shipping precedent in this repo (e.g. Keynotes.pushbutton), so those were not flagged. Localization keys are consistent across all 8 locale files. Found two real gaps in Revit-API-context/state handling:

  1. fm.CurrentType can be None for a family with no defined types yet — unguarded, this crashes refresh_from_document/_build_row (precedent: Cycle Family Types.pushbutton explicitly checks for this).
  2. on_toggle_editable_click/on_toggle_labels_click read revit.doc/doc.FamilyManager directly from a plain button-click handler, breaking the file's own convention of bridging all document access through execute_in_revit_context.

No IronPython 2.7/PEP8/black-formatting violations were spotted (no f-strings, no Py3-only syntax, consistent .format() usage).

Suggestions

  • Guard fm.CurrentType is None before reading parameter values in FamSlide. Apply
  • Route toggle-editable/toggle-labels handlers through execute_in_revit_context. Apply

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@jmcouffin

Copy link
Copy Markdown
Contributor

@dnenov good with you if this goes out?

@dnenov

dnenov commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

@dnenov good with you if this goes out?

Thank you for the effort @Wurschdhaud, thank you for letting me know and being considerate of my opinion @jmcouffin . I reviewed the code, the implementation is quite efficient and easy to maintain I reckon.

Honestly, it's difficult for me to let go of one of my first Revit add-ins like that, but the thruth is that it serves the community better if it's out in the open and maintained by said community. You have my blessing, let's make it a pyRevit addition. I will update the existing Autodesk Marketplace documentation to point to pyRevit for posterity.

(I really appreciate the credentials inside the tooltip too, that tilted the scales - my silly ego got what it wanted I suppose.)

Thank you once again @Wurschdhaud @jmcouffin

@jmcouffin

Copy link
Copy Markdown
Contributor

Reading thru the code, I understand that the shuffle needs to be rolled back from the Revit UI.
Can it be done, rolled back, from the tool? Shuffle button shuffles and disable any other button from the UI except for a 'rollback shuffle' button,
@Wurschdhaud

@Wurschdhaud

Copy link
Copy Markdown
Contributor Author

There is a store and restore button:
image

@jmcouffin

Copy link
Copy Markdown
Contributor

There is a store and restore button: image

Nice
Thinking out loud here,
Why not having the equivalent: shuffle (and store), and a specific restore button?
Or maybe just: store when opening the tool and the cancel button restore the saved values, whereas the other button applies the changes (and should be named apply)

@Wurschdhaud

Copy link
Copy Markdown
Contributor Author

I don't understand what you mean tbh - at least not for the second sentence
Triggering the save when starting is a good idea, I'll look into it

@Wurschdhaud

Copy link
Copy Markdown
Contributor Author

Added automatic save on startup - I hope that's what you meant?
Also added locked tag, and fixed an issue with string display+change

Was mostly non-AI changes, so I would appreciate another Copilot before this goes live. Will for sure have at least a typo or whatever 😄

@jmcouffin

Copy link
Copy Markdown
Contributor

Added automatic save on startup - I hope that's what you meant? Also added locked tag, and fixed an issue with string display+change

Was mostly non-AI changes, so I would appreciate another Copilot before this goes live. Will for sure have at least a typo or whatever 😄

You'll get a human review for the dame price 😁

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 16 changed files in this pull request and generated no new comments.

Suppressed comments (4)

extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/script.py:557

  • Preset capture currently falls back to fm.CurrentType.AsValueString(...) for any non-numeric storage type. For String parameters this is inconsistent with the edit path (_commit_text uses fm.Set for StorageType.String) and can lead to missing/incorrect preset values for string parameters (and unclear behavior for ElementId).
                preset[param_id] = fm.CurrentType.AsInteger(row.param)
            elif row.storage_type == DB.StorageType.Double:
                preset[param_id] = fm.CurrentType.AsDouble(row.param)
            else:
                preset[param_id] = fm.CurrentType.AsValueString(row.param)

extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/script.py:590

  • Preset restore applies SetValueString(...) for the non-numeric fallback case. This will fail for String parameters (which should use fm.Set) and does not handle ElementId values. As a result, presets saved from string parameters may not be restored correctly.
                        fm.Set(row.param, int(value))
                    elif row.storage_type == DB.StorageType.Double:
                        fm.Set(row.param, float(value))
                    else:
                        fm.SetValueString(row.param, value)

extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/script.py:611

  • The event handlers are registered via @events.handle, which keys registrations by the current EXEC_PARAMS.exec_id. In persistent-engine + modeless UI scenarios, the user can run other commands before closing FamSlide, so EXEC_PARAMS.exec_id may change; this makes events.stop_events() (called on window close) unregister the wrong handler group, leaving stale doc-changed/view-activated hooks alive and keeping the old ScriptScope/UI instance pinned.

Consider registering handlers under a stable, tool-specific handler_group_id (e.g. script.get_unique_id() or a hardcoded string) via events.register_handler(..., handler_group_id=...) and explicitly unregistering that group on close (events.unregister_exec_handlers(handler_group_id)).

@events.handle("doc-changed", "view-activated", "doc-opened")
def famslide_on_revit_event(sender, args):
    if ui is not None:
        ui.refresh_from_document()

extensions/pyRevitTools.extension/pyRevit.tab/Project.panel/ptools.stack/Family.pulldown/FamSlide.pushbutton/script.py:296

  • The value TextBox becomes editable for any editable parameter, but _commit_text only supports Double/Integer (via SetValueString) and String (via Set). This means ElementId parameters can appear editable but edits will never apply, and Yes/No parameters show localized "Yes/No" text that may not be parseable by SetValueString.

Making the TextBox read-only unless the storage type is actually supported (and excluding Yes/No, which already has a checkbox) avoids a misleading UI and failed commits.

This issue also appears in the following locations of the same file:

  • line 553
  • line 586
        value_box.IsReadOnly = not row.is_editable
        value_box.Tag = row
        value_box.KeyDown += self.on_value_box_key_down
        value_box.LostFocus += self.on_value_box_lost_focus

- set elementid to readonly
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Tools Issues related to pyRevit commands [subsystem]

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants