Сообщество программистов Autodesk в СНГ

ADN Club => Revit API => Тема начата: toxan от 31-07-2018, 09:38:44

Название: Событие - изменение значения параметра в семействе.
Отправлено: toxan от 31-07-2018, 09:38:44
Добрый день!
Подскажите, можно ли  в фоновом режиме  "увидеть" изменение параметра в определенном семействе? 
Как пример - изменение отметки семейства?


Название: Re: Собитите - изменение значения параметра в семействе.
Отправлено: Александр Пекшев aka Modis от 31-07-2018, 10:04:34
Можно. Для этого нужно использовать IUpdater (https://knowledge.autodesk.com/pt-br/support/revit-products/learn-explore/caas/CloudHelp/cloudhelp/2018/PTB/Revit-API/files/GUID-6D434229-0A2E-41FE-B29D-1BB2E6471F50-htm.html).
Там при регистрации есть варианты за чем следить - изменением геометрии, изменением параметра или за всеми изменениями.
А уже в обработчике события вы можете проверять, что это нужное вам семейство изменилось
Название: Re: Собитите - изменение значения параметра в семействе.
Отправлено: Александр Игнатович от 31-07-2018, 10:21:27
Александр, лучше не в IUpdater такое разруливать, а в фильтре, который передается при регистрации апдейтра, что-то вроде такого:
Код - C# [Выбрать]
  1. public ElementFilter CreateCableTrayUnionWithConduitSymbolFilter()
  2. {
  3.         var familyNameRule = ParameterFilterRuleFactory.CreateEqualsRule(new ElementId(BuiltInParameter.ALL_MODEL_FAMILY_NAME), CableTrayUnionWithConduitFamilyName, false);
  4.  
  5.         var symbolNameRule = ParameterFilterRuleFactory.CreateEqualsRule(new ElementId(BuiltInParameter.SYMBOL_NAME_PARAM), CableTrayUnionWithConduitFamilySymbolName, false);
  6.  
  7.         var filters = new ElementFilter[]
  8.                 {
  9.                         new ElementIsElementTypeFilter(),
  10.                         new ElementCategoryFilter(BuiltInCategory.OST_CableTrayFitting),
  11.                         new ElementParameterFilter(new [] {familyNameRule, symbolNameRule})
  12.                 };
  13.  
  14.         return new LogicalAndFilter(filters);
  15. }
Название: Re: Собитите - изменение значения параметра в семействе.
Отправлено: Александр Пекшев aka Modis от 31-07-2018, 10:23:18
а в фильтре, который передается при регистрации апдейтра
Ага, точно. Я просто забыл - под рукой не было кода никакого))
Название: Re: Собитите - изменение значения параметра в семействе.
Отправлено: Александр Игнатович от 31-07-2018, 10:32:16
Кстати, для решения задачи еще потребуется где-то хранить прошлое значение, это может быть Extensible storage или параметр проекта/семейства, возможно невидимый.

Т.е., например, 1 апдейтер реагирует на добавление элементов с фильтром по определенным критериям, читаем текущее значение параметра, пишем в extensible storage, второй апдейтер по тому же фильтру реагирует на изменение элемента, в методе Execute сравниваем значение параметра со значением, сохраненным в сторадже и, если они не совпадают, обновляем значение в сторадже и делаем что-то полезное :-)
Название: Re: Собитите - изменение значения параметра в семействе.
Отправлено: Александр Пекшев aka Modis от 31-07-2018, 10:34:30
Кстати, для решения задачи еще потребуется где-то хранить прошлое значение, это может быть Extensible storage или параметр проекта/семейства, возможно невидимый.

Т.е., например, 1 апдейтер реагирует на добавление элементов с фильтром по определенным критериям, читаем текущее значение параметра, пишем в extensible storage, второй апдейтер по тому же фильтру реагирует на изменение элемента, в методе Execute сравниваем значение параметра со значением, сохраненным в сторадже и, если они не совпадают, обновляем значение в сторадже и делаем что-то полезное :-)
Ну мы не знаем, что хочет автор вопроса, поэтому нет смысла и гадать варианты реализации =)
Например, я делал подобную штуку и мне совершенно не важно было прошлое значение - я обрабатывал только текущее (новое). Все зависит от задачи
Название: Re: Собитите - изменение значения параметра в семействе.
Отправлено: Александр Игнатович от 31-07-2018, 10:37:08
Это всё да, просто раз вопрос об изменении определенных значений, надо дать все направления, в какую сторону копать человеку
Название: Re: Собитите - изменение значения параметра в семействе.
Отправлено: Александр Игнатович от 31-07-2018, 10:40:41
Кстати, как вариант еще, если не нужно менять ничего в модели, запрещать выполнение определенных операций и т.д. можно еще рассмотреть возможность подписки на событие DocumentChanged. Оно read-only, модель изменять нельзя. Из минусов оно, по сравнению с IUpdater выдает полный перечень измененных элементов на каждый чих, лично мне больше как раз нравится IUpdater с гибкими фильтрами
Название: Re: Собитите - изменение значения параметра в семействе.
Отправлено: toxan от 31-07-2018, 13:51:56
Коллеги, голову сломал.
Нужно отследить в семействе обобщенной модели  ЗНАЧЕНИЕ параметра отметки  от уровня. 
Не могу понять с какой стороны подкопаться.
Затык именно в том как получить  значение параметра при его изменении.
Название: Re: Собитите - изменение значения параметра в семействе.
Отправлено: Александр Игнатович от 31-07-2018, 14:00:00
А в чем проблема?

Код - C# [Выбрать]
  1. var value = elem.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM).AsDouble();

При необходимости использовать UnitUtils для преобразования в метры, миллиметры или еще в какие единицы
Название: Re: Собитите - изменение значения параметра в семействе.
Отправлено: Александр Игнатович от 31-07-2018, 14:00:46
И да, для изучения модели и API крайне рекомендую поставить RevitLookup
Название: Re: Собитите - изменение значения параметра в семействе.
Отправлено: toxan от 31-07-2018, 14:16:35
Статика,  то понятна.
Хотелось бы фоном отслеживать изменение параметра.
От начала работы до закрытия файла.
Т.е. если в семействе изменился параметр - то я тут же увидел что он изменился. Т.е. я  должен получить доступ к событию изменения ЗНАЧЕНИЯ параметра  в фоновом режиме, при каждом его изменении.
Название: Re: Собитите - изменение значения параметра в семействе.
Отправлено: Александр Игнатович от 31-07-2018, 14:22:15
Тогда смотрите в теме выше.

Во-первых, есть IUpdater - его метод Execute() выполняется когда "транзакция почти завершена", в нем можно получить все добавленные / измененные элементы согласно фильтра, который передается при его регистрации, здесь можно вносить изменения в модель

Во-вторых, событие DocumentChanged, в него уже прилетают все изменения, получаем элементы, анализируем, что-то делаем (но без возможности вносить изменения в модель)
Название: Re: Собитите - изменение значения параметра в семействе.
Отправлено: toxan от 31-07-2018, 14:24:17
Нужен код который реализует:
(https://s15.postimg.cc/5xe0tb293/80e4b383dec1cb88cbfc0fe6ca32dc8c29742b4c_1_690x412.gif) (https://postimg.cc/image/5xe0tb293/)

Я БЫЛ БЫ ОЧЕНЬ ПРИЗНАТЕЛЕН, ЕСЛИ КТО-ТО ПОМОГ МНЕ С ДАННЫМ КОДОМ. 

Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: Александр Игнатович от 31-07-2018, 14:45:48
Код - C# [Выбрать]
  1. public class App : IExternalApplication
  2. {
  3.         private readonly ElementId elementId = new ElementId(706288);
  4.  
  5.         public Result OnStartup(UIControlledApplication application)
  6.         {
  7.                 application.ControlledApplication.DocumentChanged += OnDocumentChanged;
  8.  
  9.                 return Result.Succeeded;
  10.         }
  11.  
  12.         public Result OnShutdown(UIControlledApplication application)
  13.         {
  14.                 application.ControlledApplication.DocumentChanged -= OnDocumentChanged;
  15.  
  16.                 return Result.Succeeded;
  17.         }
  18.  
  19.         private void OnDocumentChanged(object sender, DocumentChangedEventArgs e)
  20.         {
  21.                 if (!e.GetModifiedElementIds().Contains(elementId))
  22.                         return;
  23.  
  24.                 var document = e.GetDocument();
  25.  
  26.                 var element = document.GetElement(elementId);
  27.  
  28.                 TaskDialog.Show("dev", element.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS).AsString());
  29.         }
  30. }
Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: enot от 01-08-2018, 12:26:36
Пробую сделать подобное , но при запуске ревит выдает ошибку (с кодом выше та же ошибка):

(https://adn-cis.org/forum/proxy.php?request=http%3A%2F%2Fipic.su%2Fimg%2Fimg7%2Ffs%2Fquestion_events_1.1533114367.png&hash=ed4053b8c1504e71b2af45c74a77f2e0)

Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: Александр Игнатович от 01-08-2018, 13:28:32
Пропустили пространство имен, я так, на самом деле даже не знаю, куда .Net положит класс без определения пространства имен, т.е. в классе должно быть что-то вроде:
Код - C# [Выбрать]
  1. namespace MP.RevitReinforcmentLibrary.RevitApp
  2. {
  3.     public class RevitApplication : IExternalApplication
  4.     {
  5.         public Result OnStartup(UIControlledApplication application)...

В манифесте addin:
Код - XML [Выбрать]
  1. ...
  2.     <Assembly>./MP.RevitReinforcmentLibrary/MP.RevitReinforcmentLibrary.RevitApp.dll</Assembly>
  3.     <FullClassName>MP.RevitReinforcmentLibrary.RevitApp.RevitApplication</FullClassName>
  4. ...
  5.  
Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: enot от 01-08-2018, 16:15:10
создать новый updaterId можно так:

Код - C# [Выбрать]
  1. static AddInId appId;
  2.     static UpdaterId updaterId;
  3.     public ParameterUpdater(AddInId id)
  4.     {
  5.        appId = id;
  6.        updaterId = new UpdaterId(appId, new Guid("...."));
  7.     }

каким образом можно получить все updaterId в Ревит? Это требуется чтобы если данный updaterId уже есть, то мы  удаляем его и привязываем к нашему событию
Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: toxan от 03-08-2018, 10:58:41
Да меня тоже данный вопрос очень интересует!
Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: Александр Игнатович от 03-08-2018, 11:20:37
Через API получить все апдейтеры я возможности не вижу, можно попробовать распарсить журнал.

Но для Вашего случая больше подходит статический метод:
Код - C# [Выбрать]
  1. UpdaterRegistry.IsUpdaterRegistered(updaterId)

Или
Код - C# [Выбрать]
  1. UpdaterRegistry.IsUpdaterRegistered(updaterId, doc)

Т.е. проверяете, зарегистрирован ли Ваш конкретный апдейтер
Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: toxan от 03-08-2018, 11:22:03
Спасибо добрый человек.
Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: Александр Игнатович от 03-08-2018, 11:26:45
Поправочка, можно получить часть информации о всех зарегистрированных апдейтерах, но там довольно немного информации, см. класс UpdaterInfo со свойствами ApplicationName, UpdaterName, IsOptional

Методы:
Код - C# [Выбрать]
  1. UpdaterRegistry.GetRegisteredUpdaterInfos()
и
Код - C# [Выбрать]
  1. UpdaterRegistry.GetRegisteredUpdaterInfos(doc)



(https://s22.postimg.cc/q6oqqt9cd/updaters.png) (https://postimg.cc/image/q6oqqt9cd/)
Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: enot от 14-08-2018, 09:55:54
Тогда смотрите в теме выше.

Во-первых, есть IUpdater - его метод Execute() выполняется когда "транзакция почти завершена", в нем можно получить все добавленные / измененные элементы согласно фильтра, который передается при его регистрации, здесь можно вносить изменения в модель

Во-вторых, событие DocumentChanged, в него уже прилетают все изменения, получаем элементы, анализируем, что-то делаем (но без возможности вносить изменения в модель)

Если нет возможности вносить изменения в модель (изменять например значение параметра элемента), то возможно ли как то в  DocumentChanged использовать метод  Execute() ? или наоборот...


Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: Александр Пекшев aka Modis от 14-08-2018, 09:59:18
Тогда смотрите в теме выше.

Во-первых, есть IUpdater - его метод Execute() выполняется когда "транзакция почти завершена", в нем можно получить все добавленные / измененные элементы согласно фильтра, который передается при его регистрации, здесь можно вносить изменения в модель

Во-вторых, событие DocumentChanged, в него уже прилетают все изменения, получаем элементы, анализируем, что-то делаем (но без возможности вносить изменения в модель)

Если нет возможности вносить изменения в модель (изменять например значение параметра элемента), то возможно ли как то в  DocumentChanged использовать метод  Execute() ? или наоборот...

Зачем вообще нужен DocumentChanged, если можно обойтись IUpdater'ом?
А вообще - конечно возможно. Вы можете нужную логику работы заложить в отдельном статическом классе и вызывать методы из него, когда требуется. Сложности будут только с контекстом Ревита и транзакцией. Но все решаемо
Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: enot от 14-08-2018, 10:07:27
Зачем вообще нужен DocumentChanged, если можно обойтись IUpdater'ом?

Я могу ошибаться, но как я заметил когда я отслеживаю изменение значения параметра через IUpdater' то он реагирует только на изменение , которое произвел пользователь - допустим мы отслеживаем координату Х элемента - IUpdater' реагирует только если вручную вбить координату. А если использовать  DocumentChanged , то он отследит изменение - когда мы перенесли элемент --> координата Х изменилась автоматом --> это изменение отследит DocumentChanged (как раз это и нужно --> чтобы записать значение в другой параметр) , а IUpdater'  нет
Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: Александр Игнатович от 14-08-2018, 10:16:01
Нет, это где-то в Вашем коде проблема, или неверный тип изменения, или с фильтром при регистрации. IUpdater-ы использую очень с давних времен и всегда успешно
Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: toxan от 19-08-2018, 12:06:50
А есть ли  метод позволяющий "просмотреть" какой метод был вызван  при нажатии кнопки мыши.

Суть проблемы в чем:
Ведомости можно разделить средствами ревита, но данный метод отсутствует в API.
Вот и возникло желание вытащить метод непосредственно из ревита.
Не дожидаясь его добавления в API.


(https://s15.postimg.cc/3ua7r3efr/image.png) (https://postimg.cc/image/3ua7r3efr/)
Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: Александр Игнатович от 20-08-2018, 10:08:39
Что происходит в Revit лучше всего описывает его журнал.

Касательно сути вопроса. Вообще Revit-овские .Net-овые библиотеки (RevitAPI.dll, RevitAPIUI.dll и прочие) содержат, как managed, так и unmanaged код и по сути являются достаточно тонким wrapper-ом для вызова функций ядра из самого Revit.

Чисто теоретически, наверное, можно попробовать применить подобный подход, хотя, как мне кажется, для этого надо как минимум иметь заголовочные .h-файлы, либо использовать механизмы pInvoke.

Да, и насколько понимаю, здесь без дизассемблирования не обойтись, что, насколько знаю, противоречит условиям лицензионного соглашения.
Название: Re: Событие - изменение значения параметра в семействе.
Отправлено: dmitrymaslakov от 19-08-2023, 13:17:05
Можно ли указать в правилах фильтра имя пользовательского параметра экземпляра, за изменениями которого нужно следить?