Skip to content

Rewrite the UI on Avalonia #469

Description

@Nice3point

Description of the new feature / enhancement

The interface runs on WPF and Wpf.Ui inside Revit.exe.
It moves to Avalonia, runs as a separate process, and communicates with Revit over RPC.

WPF is in maintenance mode.
Avalonia ships releases, renders through its own compositor, supports native AOT, and runs on every desktop platform.
The official Fluent v2 theme, added in AvaloniaUI/Avalonia#21771, replaces the design layer Wpf.Ui provides today.
Development moves to Linux, and Windows serves the Revit side alone.

Topology

flowchart LR
    subgraph revit["Revit process"]
        addin["RevitLookup add-in"] --> engine["LookupEngine"]
        addin --> visualization["DirectContext3D servers"]
    end
    subgraph ui["UI process"]
        avalonia["Avalonia application"]
    end
    addin <-->|"StreamJsonRpc over a named pipe"| avalonia
Loading

The Revit API, the engine stay on one side of the pipe.
The UI process references none of them.

Processes

Component Responsibility
Add-in Owns the Revit session, runs the engine on the Revit thread, and serves the RPC endpoint.
LookupEngine Decomposes an object and holds the live result behind a handle.
UI process Renders every window and dialog. Holds no Revit type and no live object.
Named pipe Carries every call between the two processes. The only channel between them.

The UI process

The interface compiles ahead of time into a native binary and starts without a .NET runtime on the machine.
Revit starts it at add-in load and stops it at shutdown.
A request checks the process and restarts it when it is gone.
One binary serves every installed Revit year.

Decomposition over the pipe

The UI binds to serialized nodes.
A node carries the display name, the type, the description, and the identifier of the handle it stands for.
Opening a member names the handle, and the add-in decomposes it and returns the next set of nodes.
A handle lives as long as the session that opened it.

Descriptor commands

A descriptor declares the commands it contributes, and the UI renders the declaration.
Invoking a command names the handle and the command, and the add-in runs it inside the Revit API context.
A visualization dialog becomes a settings panel over RPC, and its DirectContext3D server stays in Revit.

Playground

The Playground runs the interface against mock data without Revit.
An Aspire host composes it: the UI process, the mock add-in host, and the pipe between them start under one run configuration, and the dashboard carries the logs and traces of both.

Distribution

A release ships the per-year add-in and one native UI binary.
The add-in verifies the UI version at handshake and refuses a mismatch.

Epics

  • Spike: an AOT window, a named pipe, and a round trip into the Revit API
  • RPC transport and process lifecycle
  • The decomposition contract over the pipe
  • Descriptor commands across the boundary
  • Windows and controls on Avalonia
  • The Playground on Aspire
  • Two artifacts in the installer

Scenario when this would be used?

The interface is the product, and every session of RevitLookup runs through it.

A UI change is written and tested on Linux against mock data, and Windows runs the Revit logic alone.
The interface starts without a .NET runtime installed on the machine.
A crash of the interface leaves the Revit session intact.

Activity

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

Metadata

Metadata

Assignees

Labels

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions