Перейти к содержанию

Дайджесты за январь-февраль

Обновления гайдов и аддонов

Январь Февраль

Мониторинг серверов и редактор аддонов

Представляем вам две легенды. То, о чем можно было только мечтать, стало реальностью.

Мониторинг серверов Редактор аддонов

Подсказки из игры на вашем сайте

Теперь вы можете отображать сведения о внутриигровых элементах простым наведением курсора мыши.

Подробнее

Апдейтер аддонов

Представляем вам программу для автообновления аддонов и делимся подробностями.

Подробнее Скачать

Чиним зависание перетаскиваемых иконок!


SLA

Рекомендуемые сообщения

Чиним зависание перетаскиваемых иконок!

Не могу молчать, хочется высказаться по этому поводу. Пока я чинил баги DarkDPSMeter, мне удалось полностью разобраться с тем, что же вызывает "зависание в воздухе" перетаскиваемых иконок предметов/заклинаний. Этот баг знаком многим - потащил куда-то иконку, отпустил, и... она застряла в воздухе. Знакомо? :)

Как проверить, нет ли у вас этой проблемы? Если у вашего персонажа одеты оба кольца, то откройте окно персонажа, и перетащите, например, верхнее кольцо на нижнее. Если оно застряло - у вас проблема. Выборочно убирайте аддоны (временно перепрятывая их из папки Addons в какую-нибудь другую папку), пока не найдёте виновника.

Так вот. DarkDPSMeter больше не имеет никакого отношения к этой проблеме. Если у вас всё ещё есть эта проблема, то знайте, виноват какой-то ДРУГОЙ аддон. Найдите виновника, и сообщите мне в личку (или здесь, в этом топике), мы его с удовольствием починим! Мною были найдены 3 таких аддона:

  • AOSimpleCoords - уже починили,
  • AnatomySelfDefence - уже починили,
  • TargetOfTarget - не будем трогать, т.к. он уже морально устарел.

История проблемы:

Когда-то, я взял код drag&drop, предложенный WShad, отшлифовал его, и написал вот такой набор функций, для перетаскивания окон аддонов:

MoveExample - Перетаскивание панели (стр. 2)

Но вначале, я просто скопировал у WShad функцию OnEventDNDDropAttempt() в таком виде:

Code:
function OnEventDNDDropAttempt( params )

mission.DNDConfirmDropAttempt()

common.SetCursor( "default" )

DragNDrop.IsPicked = false

end

Самое ужасное, что эта функция срабатывает во всех аддонах КАЖДЫЙ РАЗ, когда пользователь отпускает любой перетаскиваемый объект (окно любого аддона, или любую иконку предмета/заклинания). Никто раньше не замечал в этом проблемы, потому, что ничего особо ужасного в этот момент не происходит (?) - просто все аддоны, пользующиеся этим кодом (без проверки на IsPicked) ВНЕЗАПНО выполняют весь код OnEventDNDDropAttempt(). Но там никакого вреда нет, если не считать злом ненужное пересохранение позиций окон аддонов в файл. А может, и есть вред, я не уверен.

Далее, этот код пошёл по рукам... Люди заметили, что "что-то не так" в этой функции OnEventDNDDropAttempt(), что там не хватает какой-то проверки. И тут кто-то (наверное, DarkMaster в аддоне DarkDPSMeter) придумал, что нужно проверять по params.targetId. Теоретически, такой способ должен был бы работать, но на практике это не всегда так. Но об этом расскажу чуть ниже. Вот как выглядит такой вариант:

Code:
function OnEventDNDDropAttempt( params )

if math.mod( params.targetId, DND_CONTAINER_STEP ) == DragNDrop.ID then

mission.DNDConfirmDropAttempt()

common.SetCursor( "default" )

DragNDrop.IsPicked = false

end

end

Или вот, ещё хуже, зачем-то "потерялась" строка mission.DNDConfirmDropAttempt():

Code:
function OnEventDNDDropAttempt( params )

mission.DNDConfirmDropAttempt()

if math.mod( params.targetId, DND_CONTAINER_STEP ) == DragNDrop.ID then

common.SetCursor( "default" )

DragNDrop.IsPicked = false

end

end

Такое ощущение, что люди просто не очень понимают смысл кода, поэтому, делают его ещё в 5 раз сложнее и запутаннее... Кто-то догадался вынести этот набор функций в отдельный файл DND_core.lua. Кто-то скопировал себе этот DND_core.lua, а кто-то скопировал сверх-запутанный вариант из DarkDPSMeter. А кто-то делал уродливые гибриды обоих вариантов... Но каждому нужно было что-то поменять в этом коде. Кому-то нужно было прикрутить сохранение позиции окна в конфиг-файл, кому-то нужно было сделать поддержку нескольких виджетов (как в DarkDPSMeter), кому-то ещё что-то. И часто, это выходило довольно неуклюже... И что мы теперь имеем? Количество различных мутаций кода drag&drop едва ли уступает количеству аддонов, их использующих :))) В общем, у каждого свой вариант... И что теперь делать, когда обнаружилась ошибка в первоисточнике?

Почему же виснут иконки:

Я не уверен на все 100%, но замечено, что иконки виснут, когда их кидают куда-то "не туда". Например, вы выкидываете из инвентаря "сдохшую" иконку (иконку какого-то расходника, который закончился, и иконка серого цвета). Происходит это наверняка потому, что какой-то аддон "услужливо" выполнил команду mission.DNDConfirmDropAttempt(), когда его об этом не просили. То есть, когда отпускают иконку "куда-то не туда", и система должна сказать "НЕТ", какой-то "не в меру услужливый" аддон говорит "ДА! Бросай сюда, всё в порядке!"

Как исправить:

Единственный правильный вариант был найден, как бы, случайно, это версия всё того же кода, которую я дополнил 2010-06-19. Я просто заметил, что в этой функции почему-то отсутствует проверка, и добавил её, выбрав для этой цели IsPicked:

Code:
function OnEventDNDDropAttempt( params )

if DragNDrop.IsPicked then

mission.DNDConfirmDropAttempt()

common.SetCursor( "default" )

DragNDrop.IsPicked = false

end

end

А сейчас объясню, в чём преимущество проверки по IsPicked перед проверкой по params.targetId. Во-первых, какая-то проверка здесь НУЖНА, чтобы не выполнять лишний раз ненужный код, не тормозить систему множественным пересохранением конфиг-файла, и чтобы избежать некоторых других конфликтов с другими аддонами и системой (как проблема с иконками). Во-вторых, IsPicked подходит здесь идеально, ввиду того, что если он false, то это ОДНОЗНАЧНО значит, что никто ваше окно не тащит, и реагировать на попытку дропа НЕЛЬЗЯ. А если он true, то ОДНОЗНАЧНО ваше окно тащат, и НУЖНО среагировать.

А чем же плох params.targetId, спросите вы? А вот чем. В документации к EVENT_DND_DRAG_TO написано: "Замечание. Событие может прийти после окончания drag&drop, если оно было отправлено в очередь до уведомления системы об окончании перетаскивания. Эту ситуацию надо проверять дополнительно." Так вот, в ходе экспериментов было замечено, что видимо, такая же неразбериха творится и с событием EVENT_DND_DROP_ATTEMPT. Я заметил, что иногда, в функцию OnEventDNDDropAttempt() приходит params.targetId=-1 (минус один!). Это значит, что если вы сверяете это -1 с ID перетаскиваемого окна, то они, естественно, НЕ РАВНЫ, и выходит, что перетаскивание НЕ завершено! Ваш перетаскиваемый виджет НЕ закреплён, и он теперь до конца сессии будет таскаться вместе с другими перетаскиваемыми объектами, как бездомный щенок. Именно поэтому, ЕДИНСТВЕННЫЙ правильный способ для OnEventDNDDropAttempt() - это проверка по IsPicked!

В общем. Девелоперы, уберите нахрен проверку по params.targetId в OnEventDNDDropAttempt() в своих аддонах, и, обязательно, замените её на IsPicked.

Всё.

Ссылка на комментарий
Поделиться на другие сайты

Quote:
Мною были найдены 3 таких аддона:
AOSimpleCoords - уже починили,
AnatomySelfDefence - вот-вот починим,
TargetOfTarget - не будем трогать, т.к. он уже морально устарел.

если GuildGui1b работает, то и AnatomySelfDefence должен работать - у них одинаковый файл DND_Core
для надежности я их поправил вставкой IsPicked - проверил - все работает, ничего не зависает =) осталось только залить..

нашел еще одного виновника зависания иконок - MiniMap (хотя и не знаю, что в нем можно перетаскивать)
Ссылка на комментарий
Поделиться на другие сайты

Удивительно, но один и тот же код, в разных аддонах, может вызывать, а может и не вызывать зависание иконок. Например, я знаю, что в GuildGui1b и в AnatomySelfDefence абсолютно одинаковые DND_core.lua, однако (по крайней мере, в моей системе) GuildGui1b проблем не вызывает, а AnatomySelfDefence вызывал (до сегодняшнего фикса).

Подозреваю, что здесь ещё имеют значение какие-то различия в XDB-файлах. Было подозрение на MainForm (т.к. это особенный виджет - сплошная мистика :)), но, вроде, не в нём дело. Можно было бы конечно, потратить несколько часов на поиск такого конкретного различия в XDB-файлах, но не нужно, т.к. уже известно, как именно можно исправить это в LUA.

P.S. В верхнем сообщении обновил: "AnatomySelfDefence - уже починили" :)

Ссылка на комментарий
Поделиться на другие сайты

Сам Minimap не перетаскивается, но этот же код (с некоторыми изменениями) там используется для изменения размера карты.

В моей системе, с Minimap иконки не подвисают, но если хоть у одного человека подвисают, значит НУЖНО исправить. Сегодня же исправлю.

UPD: Minimap исправлен.

Ссылка на комментарий
Поделиться на другие сайты

Привет. =)

Нет никакой мистики. Подумай в таком ключе: аддонов куча, многие подписаны на искомый ивент, и совсем никто не знает, в каком порядке будут выполнены хэндлеры этих аддонов. В таких условиях любой чих, даже само сочетание установленных аддонов может сильно влиять на проявляемость бага. Можно проверить влияние имен аддонов, уверен, оно есть. Нивальский драг-н-дроп за вами иногда не успевает. =)

По-хорошему, весь этот mission.DND... для абсолютной безбаговости должен управляться централизованно только одним специализированным аддоном. Ибо налицо ситуация острой конкуренции за эту функциональность между аддонами, которые друг о друге и не догадываются, и договориться друг с другом не могут.

Offtopic: А почему у меня превью поста кракозябрами? =( (только) Я в Опере последней живу под XP.

Ссылка на комментарий
Поделиться на другие сайты

Вот я думаю... зачем вся эта возня с ДнД?

В стандартных аддонах, если не ошибаюсь, существует всего 1(один!!!!), который можно перемещать и то после снятия соответствующей галки

Наверное это о чем то говорит, вполне возможно даже о том, что разрабы на эти свои грабли уже наступали и ничего сделать не смогли/захотели для решения

Почему, кстати, не делать так же как и у них - жмешь галку\кнопку и перемещаешь?

Ну это уже, скорее, вопрос тем, кто использует эти функции в своих аддонах

Ссылка на комментарий
Поделиться на другие сайты

Я знаю, кто во всём виноват - WShad =)) Это он откопал весь функционал D&D, и вот как выглядит его функция. Внимание, первоисточник:

Code:
function OnEventDNDDropAttempt( params )

mission.DNDConfirmDropAttempt()

end

:)))))

При правильном коде, какой у нас уже есть (когда ни один аддон не реагирует на чужие события), система D&D работает отлично. Кроме того, это не правда, что в игре D&D используется только для окна чата. Он постоянно используется для перемещения иконок предметов и заклинаний. И проблема была не в самой этой системе, а в растиражированном баге в одной из наших функций. В будущем, проблем с D&D быть не должно, при том условии, что все будут пользоваться исправленным кодом.

Ссылка на комментарий
Поделиться на другие сайты

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...

Важная информация

Пользуясь сайтом, вы принимаете Условия использования