GripOverrule: MoveGripPointsAt - отмена перемещения

Автор Тема: GripOverrule: MoveGripPointsAt - отмена перемещения  (Прочитано 7174 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Всем привет. Пробую тут освоить переопределение ручек и возник такой вопрос - как (где) происходит событие того, что ручку перенесли? Возможно не очень понятно объясняю
При вызове метода MoveGripPointsAt я меняю данные своего примитива и добавляю к нему расширенные данные. Если при перемещении ручки я нажму Esc, то примитив не изменится, а вот расширенные данные запишутся.
Я сначала подумал, что нужно использовать OnGripStatusChanged, но не уловил смысла этого метода - там всего три статуса...
В общем смысл в том, что мне нужно записать расширенные данные в примитив именно тогда, когда ручка точно перенеслась. Как это сделать?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Я бы на твоём месте писал бы эти данные в ObjectOverrule.Close - так было бы универсальнее.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Я бы на твоём месте писал бы эти данные в ObjectOverrule.Close - так было бы универсальнее.
Думал об этом. Решил вот пробовать и конечно-же столкнулся с проблемами
1. Мне нужно между Overrules (на данный момент это GripsOverrule и ObjectOverrule) передавать данные моего объекта. Т.е. в момент начала редактирования я получаю эти данные, в завершении - записываю. Вот пытаюсь осмыслить куда мне это вынести? Может сделать отдельный класс с переменной, в которой я буду хранить эти данные между началом изменения и окончанием? Тогда еще нужно решить в каком Overrule мне их получать. ObjectOverrule.Оpen подойдет?
UPD: Объясню сразу - данные, хранимые в XRecord, зависят от графики (точнее - от его местоположения). При использовании GripsOverrule в методе GetGripPoints я получаю данные, в методе MoveGripPointsAt изменяю и записываю обратно. Если начну использовать ObjectOverrule.Close, то нужно правильно разместить получение данных, изменение и расположение их обратно
2. Накидал просто тестовый код, чтобы по командной строке посмотреть, что происходит:
Код - C# [Выбрать]
  1. public class BreakLineObjectOverrule : ObjectOverrule
  2. {
  3.     protected static BreakLineObjectOverrule _breakLineObjectOverrule;
  4.     public static BreakLineObjectOverrule Instance()
  5.     {
  6.         if (_breakLineObjectOverrule == null)
  7.             _breakLineObjectOverrule = new BreakLineObjectOverrule();
  8.         return _breakLineObjectOverrule;
  9.     }
  10.  
  11.     public override void Open(DBObject dbObject, OpenMode mode)
  12.     {
  13.  
  14.         if (IsApplicable(dbObject))
  15.         {
  16.             AcadHelpers.Editor.WriteMessage("\nObjectOverrule on Open");
  17.             AcadHelpers.Editor.WriteMessage("\nObjectOverrule on Open - mode: " + mode);
  18.             AcadHelpers.Editor.WriteMessage("\nObjectOverrule on Open - ObjectId: " + dbObject.ObjectId);
  19.         }
  20.         base.Open(dbObject, mode);
  21.     }
  22.  
  23.     public override void Close(DBObject dbObject)
  24.     {
  25.         if (IsApplicable(dbObject))
  26.         {
  27.             AcadHelpers.Editor.WriteMessage("\nObjectOverrule on Close");
  28.             AcadHelpers.Editor.WriteMessage("\nObjectOverrule on Close - isModified: " + dbObject.IsModified);
  29.             AcadHelpers.Editor.WriteMessage("\nObjectOverrule on Close - IsCancelling: " + dbObject.IsCancelling);
  30.             AcadHelpers.Editor.WriteMessage("\nObjectOverrule on Close - IsErased: " + dbObject.IsErased);
  31.             AcadHelpers.Editor.WriteMessage("\nObjectOverrule on Close - IsModifiedGraphics: " + dbObject.IsModifiedGraphics);
  32.             AcadHelpers.Editor.WriteMessage("\nObjectOverrule on Close - IsUndoing: " + dbObject.IsUndoing);
  33.             AcadHelpers.Editor.WriteMessage("\nObjectOverrule on Close - ObjectId: " + dbObject.ObjectId);
  34.         }
  35.         base.Close(dbObject);
  36.     }
  37.  
  38.     public override bool IsApplicable(RXObject overruledSubject)
  39.     {
  40.         return ExtendedDataHelpers.IsApplicable(overruledSubject);
  41.         //return base.IsApplicable(overruledSubject);
  42.     }
  43. }
В итоге, сразу после создания (да и при создании) объекта я постоянно вижу в командной строке все эти надписи. Даже если я не трогаю объект, а просто вожу мышкой по экрану  :o
« Последнее редактирование: 21-05-2017, 11:31:42 от Александр Пекшев aka Modis »

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Никак не получается совместить GripOverrule и ObjectOverrule.
В момент выполнения метода GetGripPoints не происходит событий Open или Close, а значит использовать Open для чтения данных уже не получается. Хотя при других вариантах (перемещение, копирование и т.д.) именно в Open мне и нужно читать данные (предполагаю, т.к. не пробовал еще).
Дальше - при обработке Close я проверяю по нескольким условиям:
Код - C# [Выбрать]
  1. public override void Close(DBObject dbObject)
  2. {
  3.     if (dbObject != null &&
  4.         dbObject.IsModified &
  5.         !dbObject.IsUndoing &
  6.         !dbObject.IsErased &
  7.         !dbObject.IsEraseStatusToggled)
  8.     {
  9.         if (IsApplicable(dbObject))
  10.         {
  11.             AcadHelpers.Editor.WriteMessage("\nOn Close");
  12.             OverrulesInteraction.WriteToEntity();
  13.         }
  14.         base.Close(dbObject);
  15.     }
  16. }
Так вот при работе метода MoveGripPointsAt (после того как я переместил и "бросил" ручку) примитив не помечается как IsModified=true и, соответственно, данные не сохраняются. Если я убираю проверку на IsModified, то при каждом перемещении мышкой во время изменения позиции ручки происходит вызов Close, что приведет к тому, что я и спрашивал в теме - произойдет сохранение данных, даже если я отменю перемещение, нажав Esc. Мало того - отмене проверки на IsModified событие Close работает постоянно, даже если я не трогаю примитив. Вожу по экрану мышкой и в командной строке при каждом движении получаю "On Close"

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Еще вопрос - почему в методе OnGripStatusChanged не ссылки на Grip?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Еще вопрос - почему в методе OnGripStatusChanged не ссылки на Grip?
Ну так оно и в ObjectARX работает.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
А еще в методе public override void Close(DBObject dbObject) для ObjectOverrule нельзя открыть транзакцию...

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А еще в методе public override void Close(DBObject dbObject) для ObjectOverrule нельзя открыть транзакцию...
Конечно. И вообще в любых Overrule использование транзакций крайне нежелательно.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Александр Пекшев aka Modis 21-05-2017, 18:07:17

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Я сначала подумал, что нужно использовать OnGripStatusChanged, но не уловил смысла этого метода - там всего три статуса...
Это в GripOverrule.OnGripStatusChanged всего три статуса. А вот в GripData.OnGripStatusChanged статусов значительно больше:
Код - C# [Выбрать]
  1. public enum Status {
  2.   GripStart,
  3.   GripEnd,
  4.   GripAbort,
  5.   Stretch,
  6.   Move,
  7.   Rotate,
  8.   Scale,
  9.   Mirror,
  10.   DimFocusChanged,
  11.   PopUpMenu
  12. }
  13.  
Поэтому создаёшь свой класс-наследник GripData, у которого переопределяешь OnGripStatusChanged и в нём анализируешь статус:

Код - C# [Выбрать]
  1. public override void OnGripStatusChanged(
  2.    ObjectId entityId, GripData.Status newStatus
  3. )
  4. {
  5.   if (newStatus == Status.GripAbort)
  6.   {
  7.     // Здесь убираешь свои Xdata
  8.   }
  9. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
А вот в GripData.OnGripStatusChanged статусов значительно больше
Спасибо. Это помогло. При статусе GripStart во временные переменные сохраняю значения гриппов, которые были до редактирования. А при статусе GripAbort восстанавливаю их. Имеется ввиду не значения точек примитива, а свойства экземпляра класса, в которые я их пишу и которые размещаю в примитив. Ну а при статусе GripEnd произвожу сохранение в расширенные данные.
Ваш ответ является решением темы и я его помечу как решение, но! Теперь меня остро мучает вопрос использования ObjectOverrule. Второй день пробую различные варианты, но увязать работу ObjectOverrule и GripOverrule я так и не смог. Если я оставлю только GripOverrule, то все нормально решается в самом GripOverrule. Но я боюсь, что все-же придется использовать ObjectOverrule и тогда все, что я сейчас сделал с гриппами - коту под хвост =(

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Но я боюсь, что все-же придется использовать ObjectOverrule и тогда все, что я сейчас сделал с гриппами - коту под хвост =(
Не думаю. Кстати, с ObjectOverrule тут похоже не получится. Причина в том, что GripOverrule оперирует не самими примитивами в базе, а их временными клонами. Так что Close для них не будет выполнятся.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Но я боюсь, что все-же придется использовать ObjectOverrule и тогда все, что я сейчас сделал с гриппами - коту под хвост =(
Не думаю. Кстати, с ObjectOverrule тут похоже не получится. Причина в том, что GripOverrule оперирует не самими примитивами в базе, а их временными клонами. Так что Close для них не будет выполнятся.
Да, но - при выборе ручки срабатывает метод Open. При перемещении ручки постоянно поочередно срабатывают методы Open и Close. Т.е. если в последующем использовать эти методы, то придется как-то учитывать, что они вызваны не методами MoveGripPointsAt и GetGripPoints

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
У Кина Волмсли есть хороший пример с переопределением ручек: http://through-the-interface.typepad.com/through_the_interface/2012/09/overriding-the-grips-of-an-autocad-polyline-to-maintain-fillet-segments-using-net.html
В нем есть все - и обработка отмены перемещения, и сохранение промежуточных данных.

Оффлайн Александр Пекшев aka ModisАвтор темы

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
А можно как-то при работе GrpsOverrule временно отключить работу ObjectOverrule?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Думаю что нет. Скорее всего все Overrule включаются/выключаются только тогда, когда управление передаются от твоего приложения AutoCAD.
Но в принципе ты можешь попробовать сам, используя методы AddOverrule и RemoveOverrule.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение