I developed a tool, need help to get it into the new release of pyrevit

Yesterday I wrote a tool to move a viewportlabel to a point. since those labels don’t align to anything except each other, it is really hard to create any sort of consistency.
so the tool works as follows: you click a point then you click a viewport and the viewportlabel moves to the point, simple.
The tool is written in C# without any dependencies other than the RevitAPI.
I don’t know a lot about github and the approval process that goes with it. if someone could help me that would be great.
I think it is a tool a lot of Revit users could benefit from

move viewportlabel to point

1 Like

you could drop the code here and I am sure I could add this feature to pyRevit tools (and credit you)

using System;
using System.Collections.Generic;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;

namespace MoveLabelToPoint
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]

    public class Analysis
    {
        public static void MoveViewportLabel(Viewport viewport, XYZ point)
        { 
            XYZ viewminpoint = viewport.GetBoxOutline().MinimumPoint;
            XYZ P = point.Subtract(viewminpoint);
            viewport.LabelOffset = P;
        }
    }
    public class Extraction
    {
        public static XYZ singlePointSelection(UIApplication uiapp)
        {
            Document doc = uiapp.ActiveUIDocument.Document;
            Selection sel = uiapp.ActiveUIDocument.Selection;
            XYZ pickPoint = sel.PickPoint();
            return pickPoint;
        }
        public static Viewport singleViewportSelection(UIApplication uiapp)
        {
            Document doc = uiapp.ActiveUIDocument.Document;
            Selection sel = uiapp.ActiveUIDocument.Selection;
            ISelectionFilter filter = new ViewportSelectionFilter();
            Reference pickref = sel.PickObject(ObjectType.Element, filter, "SelectViewport");
            Viewport Selected = doc.GetElement(pickref) as Viewport;
            return Selected;
        }
        
        public class ViewportSelectionFilter : ISelectionFilter
        {
            public bool AllowElement(Element element)
            {
                return element.Category.Name == "Viewports";
            }

            public bool AllowReference(Reference reference, XYZ position)
            {
                return false;
            }
        }
    }

    public class _08_ViewportLabelOnPoint : IExternalCommand
    {
        
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {

            //Selection or Extraction
            UIApplication uiapp = commandData.Application;
            Document doc = uiapp.ActiveUIDocument.Document;
            Boolean flag = true;
            while (flag)
            {
                try
                {
                    XYZ selectedPoint = Extraction.singlePointSelection(uiapp);
                    Viewport selectedViewport = Extraction.singleViewportSelection(uiapp);

                    //Creation
                    Transaction trans = new Transaction(doc);
                    trans.Start("Move Label to Point");
                    //Creation Process
                    Analysis.MoveViewportLabel(selectedViewport, selectedPoint);
                    trans.Commit();
                    
                }
                catch
                {
                    flag = false;
                }
            }
            return Result.Succeeded;
        }
    }
}


Hi @TimHevel , thanks for the contribution!

Some remarks about your code:

  1. In the singlePointSelection method you don’t need a transaction to pick a point… it all boils down to `return uiapp.ActiveUIDocument.Selection.PickPoint();
  2. same with the singleViewportSelection, you’re not modifying the database, so you should’t need to create and commit transactions.
  3. In any case, when there’s an error you should’t commit anything, but Rollback()
  4. initalizing objects to null is not needed, just return the selection directly in the try block and return null inside the catch block
  5. the AllowElement method can be a one liner: return element.Category.Name == "Viewports"
  6. Transactions should be properly disposed after use, either with the Dispose() method or creating them with the using directive. The Transaction API docs has an example on how to do it.
  7. you should be more specific about what exception you are catching, especially in the last catch (the only one that should be there). What if the exception causes an error on the functionality of the command? In that case, you should not silence it and return Result.Succeeded

@sanzoghenzo I will change your title to: Code Etiquette Guardian :smile:

3 Likes

7 Likes

most of it was how it was taught in the Udemy Course :sweat_smile:

I already edited the part where the transaction didn’t close properly.

I removed the other two catches

:sweat_smile: no one is perfect, not even a Udemy course :rofl:

the new tool is coming
@TimHevel thanks

2 Likes

doesn’t it need a while loop or something so you don’t have to click the button for each viewport?
I notice it is also a lot slower in python

Not on my computer.

That or press the enter key to repeat the last command
Feel free to PR to add the while loop