Jump to content
Alloder.pro: about Allods with love
Search In
  • More options...
Find results that contain...
Find results in...

New program for writers

We turn from quantity to quality and tell you how we will supplement the Allods Team program with rewards in rubles.

More

The new Updater

Let us to introduce the new addon updater software and to share the details

Read more

Alloder 2.0

We have started the process of project evolve, and this relates not only, and not even primarily of the site's view

Read more

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


SLA
 Share

Recommended Posts

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

Не могу молчать, хочется высказаться по этому поводу. Пока я чинил баги 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.

Всё.

Link to comment
Share on other sites

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

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

нашел еще одного виновника зависания иконок - MiniMap (хотя и не знаю, что в нем можно перетаскивать)
Link to comment
Share on other sites

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

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

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

Link to comment
Share on other sites

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

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

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

Link to comment
Share on other sites

Привет. =)

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

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

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

Link to comment
Share on other sites

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

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

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

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

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

Link to comment
Share on other sites

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

Code:
function OnEventDNDDropAttempt( params )

mission.DNDConfirmDropAttempt()

end

:)))))

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

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

By using our site you agree to the Terms of Use