Complete novice here trying to make my first plugin for pyRevit. I have little to no coding knowlege so I used chatGPT to write this code but I can’t seem to get past the following error:
AttributeError: ‘NoneType’ object has no attribute ‘ActiveUIDocument’
import clr
import math
from Autodesk.Revit.DB import *
from Autodesk.Revit.UI import TaskDialog
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
clr.AddReference("System")
from System.Collections.Generic import List
# Get the current Revit document and UI document
def get_revit_context():
try:
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
if not doc:
TaskDialog.Show("Error", "Revit DB Document is None. Ensure that the script is running in Revit.")
raise Exception("Revit DB Document is None")
if not uidoc:
TaskDialog.Show("Error", "Revit UI Document is None. Ensure that the script is running in Revit.")
raise Exception("Revit UI Document is None")
return doc, uidoc
except Exception as e:
TaskDialog.Show("Error", str(e))
raise
doc, uidoc = get_revit_context()
def set_leader_angle(leader, angle_radians):
"""
Set the angle of a leader based on the angle from the y-axis (in radians).
"""
# Get the start and end points of the leader
leader_elbow = leader.Elbow
leader_head = leader.Head
# Calculate new elbow point based on the angle provided
dy = leader_elbow.Y - leader_head.Y
dx = dy * math.tan(angle_radians)
new_elbow = XYZ(leader_head.X + dx, leader_elbow.Y, leader_elbow.Z)
# Set new elbow location
leader.Elbow = new_elbow
def get_user_angle_input():
"""
Prompts the user to enter an angle (in degrees) for the leader lines.
"""
input_dialog = TaskDialog("Input Leader Angle")
input_dialog.MainInstruction = "Enter the angle in degrees (bearing from the y-axis):"
input_dialog.MainContent = "You can set the leader angle to be applied to the selected tags."
angle_input = input("Angle (in degrees): ")
try:
return float(angle_input)
except ValueError:
TaskDialog.Show("Error", "Invalid angle input. Please enter a valid number.")
return None
def select_tags():
"""
Prompt the user to select multiple tags in Revit.
"""
uidoc.PromptForSelectionStatusText = "Select tag(s) to set leader angle. Finish selection with Enter/Spacebar"
selected_tags = uidoc.Selection.PickObjects(ObjectType.Element, "Select the tags to modify.")
return [doc.GetElement(tag.ElementId) for tag in selected_tags]
def filter_tags_with_leaders(tags):
"""
Filters out tags that do not have leaders and informs the user.
"""
tags_with_leaders = []
tags_without_leaders = []
for tag in tags:
if tag.HasLeader and tag.Leader.HasElbow:
tags_with_leaders.append(tag)
else:
tags_without_leaders.append(tag)
if tags_without_leaders:
TaskDialog.Show("Warning", "{} tags without leaders were ignored.".format(len(tags_without_leaders)))
return tags_with_leaders
def run_plugin():
"""
Main function to run the plugin.
"""
# Let the user choose between inputting an angle or selecting a base tag
base_tag_selection = TaskDialog.Show("Choose Mode", "Do you want to select a base tag or input an angle?",
TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No)
# Option 1: User selects a base tag and copies its leader angle to other tags
if base_tag_selection == TaskDialogResult.Yes:
uidoc.PromptForSelectionStatusText = "Select a single base tag"
base_tag = uidoc.Selection.PickObject(ObjectType.Element, "Pick the base tag with the desired leader angle")
base_leader = doc.GetElement(base_tag.ElementId).Leader
# Ensure the base tag has a leader
if not base_leader.HasElbow:
TaskDialog.Show("Error", "The selected base tag does not have a leader.")
return
base_leader_angle = math.atan2(base_leader.Elbow.X - base_leader.Head.X,
base_leader.Elbow.Y - base_leader.Head.Y)
# Prompt user to select other tags to match the leader angle
uidoc.PromptForSelectionStatusText = "Pick tag(s) to match leader angle"
selected_tags = select_tags()
# Filter out tags without leaders
selected_tags = filter_tags_with_leaders(selected_tags)
# Apply base leader angle to all selected tags
with Transaction(doc, "Set Leader Angle") as t:
t.Start()
for tag in selected_tags:
leader = tag.Leader
set_leader_angle(leader, base_leader_angle)
t.Commit()
# Option 2: User inputs an angle manually
else:
angle_degrees = get_user_angle_input()
if angle_degrees is None:
return
# Convert degrees to radians
angle_radians = math.radians(angle_degrees)
# Prompt user to select tags to set the angle
selected_tags = select_tags()
# Filter out tags without leaders
selected_tags = filter_tags_with_leaders(selected_tags)
# Apply the specified angle to all selected tags
with Transaction(doc, "Set Leader Angle") as t:
t.Start()
for tag in selected_tags:
leader = tag.Leader
set_leader_angle(leader, angle_radians)
t.Commit()
TaskDialog.Show("Success", "Leader angles have been updated.")
# Run the plugin
if __name__ == "__main__":
run_plugin()
I am trying to create a plugin that will match all the leader lines of a tag to the same angle.
I have no idea what I am doing so any help would be appreciated.