Files
2024-12-12 09:51:40 +01:00

395 lines
14 KiB
VB.net

#Region "Copyright"
''
'' (C) Copyright 2010 by Autodesk, Inc.
''
'' Permission to use, copy, modify, and distribute this software in
'' object code form for any purpose and without fee is hereby granted,
'' provided that the above copyright notice appears in all copies and
'' that both that copyright notice and the limited warranty and
'' restricted rights notice below appear in all supporting
'' documentation.
''
'' AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
'' AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
'' MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
'' DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
'' UNINTERRUPTED OR ERROR FREE.
''
'' Use, duplication, or disclosure by the U.S. Government is subject to
'' restrictions set forth in FAR 52.227-19 (Commercial Computer
'' Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
'' (Rights in Technical Data and Computer Software), as applicable.
''
'' Written by M.Harada
''
#End Region
#Region "Imports"
'' Import the following name spaces in the project properties/references.
'' Note: VB.NET has a slighly different way of recognizing name spaces than C#.
'' if you explicitely set them in each .vb file, you will need to specify full name spaces.
'Imports System
'Imports Autodesk.Revit.DB
'Imports Autodesk.Revit.UI
'Imports Autodesk.Revit.ApplicationServices '' Application class
'Imports Autodesk.Revit.Attributes '' specific this if you want to save typing for attributes. e.g.,
'Imports Autodesk.Revit.UI.Selection '' for selection
'Imports Autodesk.Revit.DB.Events '' this is for Lab4 event.
'Imports Autodesk.Revit.UI.Events '' this is for lab4 event.
#End Region
'' Event
''
'' cf. Developer Guide, Section 24 Event(pp278) - list of events you can subscribe
'' Appexdix G. API User Interface Guidelines (pp381), Task Dialog (pp404)
''
'' external application to register/unregister document changed event.
'' simple reports what has been changed
''
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class UIEventApp
Implements IExternalApplication
'' flag to indicate if we want to show a message at each object modified events.
Public Shared m_showEvent As Boolean = False
'' OnShutdown() - called when Revit ends.
''
Public Function OnShutdown(ByVal application As UIControlledApplication) As Result _
Implements IExternalApplication.OnShutdown
'' (1) unregister our document changed event hander
RemoveHandler application.ControlledApplication.DocumentChanged, AddressOf UILabs_DocumentChanged
Return Result.Succeeded
End Function
'' OnStartup() - called when Revit starts.
''
Public Function OnStartup(ByVal application As UIControlledApplication) As Result _
Implements IExternalApplication.OnStartup
'' (1) resgister our document changed event hander
AddHandler application.ControlledApplication.DocumentChanged, AddressOf UILabs_DocumentChanged
'' (2) register our dynamic model updater (WindowDoorUpdater class definition below.)
'' we are going to keep doors and windows at the center of the wall.
''
'' construct our updater.
Dim winDoorUpdater As New WindowDoorUpdater(application.ActiveAddInId) '' ActiveAddInId is from addin menifest.
'' register it
UpdaterRegistry.RegisterUpdater(winDoorUpdater)
'' tell which elements we are interested in notified.
'' we want to know when wall changes it's length.
''
Dim wallFilter As New ElementClassFilter(GetType(Wall))
UpdaterRegistry.AddTrigger(winDoorUpdater.GetUpdaterId(), wallFilter, Element.GetChangeTypeGeometry)
Return Result.Succeeded
End Function
'' This is our event handler. Simply report the list of element ids which have been changed.
''
Sub UILabs_DocumentChanged(ByVal sender As Object, ByVal args As DocumentChangedEventArgs)
If Not m_showEvent Then Return
'' you can get the list of ids of element added/changed/modified.
Dim rvtdDoc As Document = args.GetDocument
Dim idsAdded As ICollection(Of ElementId) = args.GetAddedElementIds()
Dim idsDeleted As ICollection(Of ElementId) = args.GetDeletedElementIds()
Dim idsModified As ICollection(Of ElementId) = args.GetModifiedElementIds()
'' put it in a string to show to the user.
Dim msg As String = "Added: "
For Each id As ElementId In idsAdded
msg += id.IntegerValue.ToString + " "
Next
msg += vbCr + "Deleted: "
For Each id As ElementId In idsDeleted
msg += id.IntegerValue.ToString + " "
Next
msg += vbCr + "Modified: "
For Each id As ElementId In idsModified
msg += id.IntegerValue.ToString + " "
Next
'' show a message to a user.
Dim res As TaskDialogResult
res = TaskDialog.Show("Revit UI Labs - Event", msg, TaskDialogCommonButtons.Ok Xor TaskDialogCommonButtons.Cancel)
'' if the user chooses to cancel, show no more event.
If (res = TaskDialogResult.Cancel) Then
m_showEvent = False
End If
End Sub
End Class
''
'' extrenal command to toggle event message on/off
''
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class UIEvent
Implements IExternalCommand
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements IExternalCommand.Execute
If UIEventApp.m_showEvent Then
UIEventApp.m_showEvent = False
Else
UIEventApp.m_showEvent = True
End If
Return Result.Succeeded
End Function
End Class
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class UIEventOn
Implements IExternalCommand
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements IExternalCommand.Execute
UIEventApp.m_showEvent = True
Return Result.Succeeded
End Function
End Class
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class UIEventOff
Implements IExternalCommand
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements IExternalCommand.Execute
UIEventApp.m_showEvent = False
Return Result.Succeeded
End Function
End Class
''========================================================
'' dynamic model update - derive from IUpdater class
''========================================================
Public Class WindowDoorUpdater
Implements IUpdater
'' member variables
Dim m_addinId As AddInId = Nothing '' this value comes from the addin manifest AddInId.
Dim m_updaterId As UpdaterId = Nothing '' unique id for this updater = addin GUID + GUID for this specific updater.
'' flag to indicate if we want to perform
Public Shared m_updateActive As Boolean = False
'' constructor
''
Sub New(ByVal id As AddInId)
m_addinId = id
m_updaterId = New UpdaterId(m_addinId, New Guid("EF43510F-38CB-4980-844C-72174A674D56"))
End Sub
'' this is the main function to do the actual job.
'' for this exercise, we assume that we want to keep the door and window always at the center.
''
Public Sub Execute(ByVal data As UpdaterData) Implements IUpdater.Execute
If Not m_updateActive Then Return
Dim rvtDoc As Document = data.GetDocument
Dim idsModified As ICollection(Of ElementId) = data.GetModifiedElementIds
For Each id As ElementId In idsModified
Dim aWall As Wall = rvtDoc.Element(id)
CenterWindowDoor(rvtDoc, aWall)
Next
End Sub
'' helper function for Execute.
'' checks if there is a door or a window on the given wall.
'' if it does, adjust the location to the center of the wall.
'' for simplify, we assume there is only one door or window.
'' (TBD: or evenly if there are more than one.)
''
Sub CenterWindowDoor(ByVal rvtDoc As Document, ByVal aWall As Wall)
'' find a winow or a door on the wall.
Dim elem As FamilyInstance = FindWindowDoorOnWall(rvtDoc, aWall)
If elem Is Nothing Then Return
'' move the element (door or window) to the center of the wall.
'' center of the wall
Dim wallLocationCurve As LocationCurve = aWall.Location
Dim pt1 As XYZ = wallLocationCurve.Curve.EndPoint(0)
Dim pt2 As XYZ = wallLocationCurve.Curve.EndPoint(1)
Dim midPt As XYZ = (pt1 + pt2) * 0.5
''
Dim loc As LocationPoint = elem.Location
'Dim newPoint As Point = rvtDoc.Application.Create.NewPoint(midPt)
loc.Point = midPt
End Sub
'' helper function
'' find a door or window on the given wall.
'' if it does, return it.
''
Function FindWindowDoorOnWall(ByVal rvtDoc As Document, ByVal aWall As Wall) As FamilyInstance
'' collect the list of windows and doors
'' no object relation graph. so going hard way.
'' list all the door instances
Dim windowDoorCollector = New FilteredElementCollector(rvtDoc)
windowDoorCollector.OfClass(GetType(FamilyInstance))
Dim windowFilter As New ElementCategoryFilter(BuiltInCategory.OST_Windows)
Dim doorFilter As New ElementCategoryFilter(BuiltInCategory.OST_Doors)
Dim windowDoorFilter As New LogicalOrFilter(windowFilter, doorFilter)
windowDoorCollector.WherePasses(windowDoorFilter)
Dim windowDoorList As IList(Of Element) = windowDoorCollector.ToElements
'' check to see if the door or window is on the wall we got.
For Each elem As FamilyInstance In windowDoorList
If elem.Host.Id.Equals(aWall.Id) Then
Return elem
End If
Next
'' if you come here, you did not find window or door on the given wall.
Return Nothing
End Function
'' this will be shown when the updated in not loaded.
Public Function GetAdditionalInformation() As String Implements IUpdater.GetAdditionalInformation
Return "Door/Window updater: keeps doors and windows at the center of walls."
End Function
'' specify the order of execusing updates.
Public Function GetChangePriority() As ChangePriority Implements IUpdater.GetChangePriority
Return ChangePriority.DoorsOpeningsWindows
End Function
'' return updater id.
Public Function GetUpdaterId() As UpdaterId Implements IUpdater.GetUpdaterId
Return m_updaterId
End Function
'' user friendly name of the updater
Public Function GetUpdaterName() As String Implements IUpdater.GetUpdaterName
Return "Window/Door Updater"
End Function
End Class
''
'' extrenal command to toggle windowDoor updater on/off
''
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class UIDynamicModelUpdate
Implements IExternalCommand
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements IExternalCommand.Execute
If WindowDoorUpdater.m_updateActive Then
WindowDoorUpdater.m_updateActive = False
Else
WindowDoorUpdater.m_updateActive = True
End If
Return Result.Succeeded
End Function
End Class
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class UIDynamicModelUpdateOn
Implements IExternalCommand
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements IExternalCommand.Execute
WindowDoorUpdater.m_updateActive = True
Return Result.Succeeded
End Function
End Class
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class UIDynamicModelUpdateOff
Implements IExternalCommand
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) _
As Result _
Implements IExternalCommand.Execute
WindowDoorUpdater.m_updateActive = False
Return Result.Succeeded
End Function
End Class